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 {
109 static const unsigned MinABIStackAlignInBytes = 4;
111 bool IsDarwinVectorABI;
112 bool IsRetSmallStructInRegABI;
113 bool IsWin32StructABI;
117 unsigned DefaultNumRegisterParameters;
119 static bool isRegisterSize(
unsigned Size) {
120 return (Size == 8 || Size == 16 || Size == 32 || Size == 64);
123 bool isHomogeneousAggregateBaseType(QualType Ty)
const override {
125 return isX86VectorTypeForVectorCall(getContext(), Ty);
128 bool isHomogeneousAggregateSmallEnough(
const Type *Ty,
129 uint64_t NumMembers)
const override {
131 return isX86VectorCallAggregateSmallEnough(NumMembers);
134 bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context)
const;
138 ABIArgInfo getIndirectResult(QualType Ty,
bool ByVal, CCState &State)
const;
140 ABIArgInfo getIndirectReturnResult(QualType Ty, CCState &State)
const;
143 unsigned getTypeStackAlignInBytes(QualType Ty,
unsigned Align)
const;
145 Class classify(QualType Ty)
const;
148 unsigned ArgIndex)
const;
152 bool updateFreeRegs(QualType Ty, CCState &State)
const;
154 bool shouldAggregateUseDirect(QualType Ty, CCState &State,
bool &InReg,
155 bool &NeedsPadding)
const;
156 bool shouldPrimitiveUseInReg(QualType Ty, CCState &State)
const;
158 bool canExpandIndirectArgument(QualType Ty)
const;
162 void rewriteWithInAlloca(CGFunctionInfo &FI)
const;
164 void addFieldToArgStruct(SmallVector<llvm::Type *, 6> &FrameFields,
165 CharUnits &StackOffset, ABIArgInfo &Info,
166 QualType
Type)
const;
167 void runVectorCallFirstPass(CGFunctionInfo &FI, CCState &State)
const;
171 void computeInfo(CGFunctionInfo &FI)
const override;
172 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
173 AggValueSlot Slot)
const override;
175 X86_32ABIInfo(CodeGen::CodeGenTypes &CGT,
bool DarwinVectorABI,
176 bool RetSmallStructInRegABI,
bool Win32StructABI,
177 unsigned NumRegisterParameters,
bool SoftFloatABI)
178 : ABIInfo(CGT), IsDarwinVectorABI(DarwinVectorABI),
179 IsRetSmallStructInRegABI(RetSmallStructInRegABI),
180 IsWin32StructABI(Win32StructABI), IsSoftFloatABI(SoftFloatABI),
181 IsMCUABI(CGT.getTarget().
getTriple().isOSIAMCU()),
182 IsLinuxABI(CGT.getTarget().
getTriple().isOSLinux() ||
183 CGT.getTarget().
getTriple().isOSCygMing()),
184 DefaultNumRegisterParameters(NumRegisterParameters) {}
189 explicit X86_32SwiftABIInfo(CodeGenTypes &CGT)
190 : SwiftABIInfo(CGT,
false) {}
193 bool AsReturnValue)
const override {
198 return occupiesMoreThan(ComponentTys, 3);
204 X86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
bool DarwinVectorABI,
205 bool RetSmallStructInRegABI,
bool Win32StructABI,
206 unsigned NumRegisterParameters,
bool SoftFloatABI)
207 : TargetCodeGenInfo(std::make_unique<X86_32ABIInfo>(
208 CGT, DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI,
209 NumRegisterParameters, SoftFloatABI)) {
210 SwiftInfo = std::make_unique<X86_32SwiftABIInfo>(CGT);
213 static bool isStructReturnInRegABI(
214 const llvm::Triple &Triple,
const CodeGenOptions &Opts);
216 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
217 CodeGen::CodeGenModule &CGM)
const override;
219 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM)
const override {
225 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
226 llvm::Value *Address)
const override;
228 llvm::Type* adjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
229 StringRef Constraint,
230 llvm::Type* Ty)
const override {
231 return X86AdjustInlineAsmType(CGF, Constraint, Ty);
234 void addReturnRegisterOutputs(CodeGenFunction &CGF, LValue ReturnValue,
235 std::string &Constraints,
236 std::vector<llvm::Type *> &ResultRegTypes,
237 std::vector<llvm::Type *> &ResultTruncRegTypes,
238 std::vector<LValue> &ResultRegDests,
239 std::string &AsmString,
240 unsigned NumOutputs)
const override;
242 StringRef getARCRetainAutoreleasedReturnValueMarker()
const override {
243 return "movl\t%ebp, %ebp"
244 "\t\t// marker for objc_retainAutoreleaseReturnValue";
260 std::string &AsmString) {
262 llvm::raw_string_ostream OS(Buf);
264 while (Pos < AsmString.size()) {
265 size_t DollarStart = AsmString.find(
'$', Pos);
266 if (DollarStart == std::string::npos)
267 DollarStart = AsmString.size();
268 size_t DollarEnd = AsmString.find_first_not_of(
'$', DollarStart);
269 if (DollarEnd == std::string::npos)
270 DollarEnd = AsmString.size();
271 OS << StringRef(&AsmString[Pos], DollarEnd - Pos);
273 size_t NumDollars = DollarEnd - DollarStart;
274 if (NumDollars % 2 != 0 && Pos < AsmString.size()) {
276 size_t DigitStart = Pos;
277 if (AsmString[DigitStart] ==
'{') {
281 size_t DigitEnd = AsmString.find_first_not_of(
"0123456789", DigitStart);
282 if (DigitEnd == std::string::npos)
283 DigitEnd = AsmString.size();
284 StringRef OperandStr(&AsmString[DigitStart], DigitEnd - DigitStart);
285 unsigned OperandIndex;
286 if (!OperandStr.getAsInteger(10, OperandIndex)) {
287 if (OperandIndex >= FirstIn)
288 OperandIndex += NumNewOuts;
296 AsmString = std::move(Buf);
300void X86_32TargetCodeGenInfo::addReturnRegisterOutputs(
302 std::vector<llvm::Type *> &ResultRegTypes,
303 std::vector<llvm::Type *> &ResultTruncRegTypes,
304 std::vector<LValue> &ResultRegDests, std::string &AsmString,
305 unsigned NumOutputs)
const {
310 if (!Constraints.empty())
312 if (RetWidth <= 32) {
313 Constraints +=
"={eax}";
314 ResultRegTypes.push_back(CGF.
Int32Ty);
318 ResultRegTypes.push_back(CGF.
Int64Ty);
322 llvm::Type *CoerceTy = llvm::IntegerType::get(CGF.
getLLVMContext(), RetWidth);
323 ResultTruncRegTypes.push_back(CoerceTy);
326 ReturnSlot.setAddress(ReturnSlot.getAddress().withElementType(CoerceTy));
327 ResultRegDests.push_back(ReturnSlot);
334bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty,
335 ASTContext &Context)
const {
340 if ((IsMCUABI && Size > 64) || (!IsMCUABI && !isRegisterSize(Size)))
346 if (Size == 64 || Size == 128)
361 return shouldReturnTypeInRegister(AT->getElementType(), Context);
372 for (
const auto *FD : RD->fields()) {
378 if (!shouldReturnTypeInRegister(FD->getType(), Context))
387 Ty = CTy->getElementType();
396 uint64_t Size = Context.getTypeSize(Ty);
397 return Size == 32 || Size == 64;
402 for (
const auto *FD : RD->
fields()) {
412 if (FD->isBitField())
415 Size += Context.getTypeSize(FD->getType());
437bool X86_32ABIInfo::canExpandIndirectArgument(QualType Ty)
const {
443 if (
const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
444 if (!IsWin32StructABI) {
447 if (!CXXRD->isCLike())
451 if (CXXRD->isDynamicClass())
462 return Size == getContext().getTypeSize(Ty);
465ABIArgInfo X86_32ABIInfo::getIndirectReturnResult(QualType RetTy, CCState &State)
const {
468 if (State.CC != llvm::CallingConv::X86_FastCall &&
469 State.CC != llvm::CallingConv::X86_VectorCall && State.FreeRegs) {
472 return getNaturalAlignIndirectInReg(RetTy);
474 return getNaturalAlignIndirect(
475 RetTy, getDataLayout().getAllocaAddrSpace(),
479ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
480 CCState &State)
const {
486 if ((State.CC == llvm::CallingConv::X86_VectorCall ||
487 State.CC == llvm::CallingConv::X86_RegCall) &&
488 isHomogeneousAggregate(RetTy, Base, NumElts)) {
493 if (
const VectorType *VT = RetTy->
getAs<VectorType>()) {
495 if (IsDarwinVectorABI) {
503 llvm::Type::getInt64Ty(getVMContext()), 2));
507 if ((Size == 8 || Size == 16 || Size == 32) ||
508 (Size == 64 && VT->getNumElements() == 1))
512 return getIndirectReturnResult(RetTy, State);
522 return getIndirectReturnResult(RetTy, State);
526 return getIndirectReturnResult(RetTy, State);
533 if (
const ComplexType *CT = RetTy->
getAs<ComplexType>()) {
534 QualType ET = getContext().getCanonicalType(CT->getElementType());
537 llvm::Type::getHalfTy(getVMContext()), 2));
542 if (shouldReturnTypeInRegister(RetTy, getContext())) {
551 if ((!IsWin32StructABI && SeltTy->isRealFloatingType())
552 || SeltTy->hasPointerRepresentation())
560 return getIndirectReturnResult(RetTy, State);
565 RetTy = ED->getIntegerType();
567 if (
const auto *EIT = RetTy->
getAs<BitIntType>())
568 if (EIT->getNumBits() > 64)
569 return getIndirectReturnResult(RetTy, State);
575unsigned X86_32ABIInfo::getTypeStackAlignInBytes(QualType Ty,
576 unsigned Align)
const {
579 if (Align <= MinABIStackAlignInBytes)
590 if (Ty->
isVectorType() && (Align == 16 || Align == 32 || Align == 64))
594 if (!IsDarwinVectorABI) {
596 return MinABIStackAlignInBytes;
604 return MinABIStackAlignInBytes;
607ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty,
bool ByVal,
608 CCState &State)
const {
610 if (State.FreeRegs) {
613 return getNaturalAlignIndirectInReg(Ty);
615 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
620 unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
621 unsigned StackAlign = getTypeStackAlignInBytes(Ty, TypeAlign);
625 getDataLayout().getAllocaAddrSpace(),
630 bool Realign = TypeAlign > StackAlign;
633 getDataLayout().getAllocaAddrSpace(),
true,
637X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty)
const {
642 if (
const BuiltinType *BT =
T->
getAs<BuiltinType>()) {
644 if (K == BuiltinType::Float || K == BuiltinType::Double)
650bool X86_32ABIInfo::updateFreeRegs(QualType Ty, CCState &State)
const {
651 if (!IsSoftFloatABI) {
657 unsigned Size = getContext().getTypeSize(Ty);
658 unsigned SizeInRegs = (
Size + 31) / 32;
664 if (SizeInRegs > State.FreeRegs) {
673 if (SizeInRegs > State.FreeRegs || SizeInRegs > 2)
677 State.FreeRegs -= SizeInRegs;
681bool X86_32ABIInfo::shouldAggregateUseDirect(QualType Ty, CCState &State,
683 bool &NeedsPadding)
const {
690 NeedsPadding =
false;
693 if (!updateFreeRegs(Ty, State))
699 if (State.CC == llvm::CallingConv::X86_FastCall ||
700 State.CC == llvm::CallingConv::X86_VectorCall ||
701 State.CC == llvm::CallingConv::X86_RegCall) {
702 if (getContext().getTypeSize(Ty) <= 32 && State.FreeRegs)
711bool X86_32ABIInfo::shouldPrimitiveUseInReg(QualType Ty, CCState &State)
const {
712 bool IsPtrOrInt = (getContext().getTypeSize(Ty) <= 32) &&
716 if (!IsPtrOrInt && (State.CC == llvm::CallingConv::X86_FastCall ||
717 State.CC == llvm::CallingConv::X86_VectorCall))
720 if (!updateFreeRegs(Ty, State))
723 if (!IsPtrOrInt && State.CC == llvm::CallingConv::X86_RegCall)
730void X86_32ABIInfo::runVectorCallFirstPass(CGFunctionInfo &FI, CCState &State)
const {
740 MutableArrayRef<CGFunctionInfoArgInfo> Args = FI.
arguments();
741 for (
int I = 0, E = Args.size(); I < E; ++I) {
744 const QualType &Ty = Args[I].type;
746 isHomogeneousAggregate(Ty, Base, NumElts)) {
747 if (State.FreeSSERegs >= NumElts) {
748 State.FreeSSERegs -= NumElts;
750 State.IsPreassigned.set(I);
756ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State,
757 unsigned ArgIndex)
const {
759 bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
760 bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
761 bool IsVectorCall = State.CC == llvm::CallingConv::X86_VectorCall;
764 TypeInfo TI = getContext().getTypeInfo(Ty);
771 return getIndirectResult(Ty,
false, State);
772 }
else if (State.IsDelegateCall) {
775 ABIArgInfo Res = getIndirectResult(Ty,
false, State);
788 if ((IsRegCall || IsVectorCall) &&
789 isHomogeneousAggregate(Ty, Base, NumElts)) {
790 if (State.FreeSSERegs >= NumElts) {
791 State.FreeSSERegs -= NumElts;
796 return getDirectX86Hva();
804 return getIndirectResult(Ty,
false, State);
810 if (RT && RT->getDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())
811 return getIndirectResult(Ty,
true, State);
814 if (!IsWin32StructABI &&
isEmptyRecord(getContext(), Ty,
true))
821 llvm::LLVMContext &LLVMContext = getVMContext();
822 llvm::IntegerType *
Int32 = llvm::Type::getInt32Ty(LLVMContext);
823 bool NeedsPadding =
false;
825 if (shouldAggregateUseDirect(Ty, State, InReg, NeedsPadding)) {
826 unsigned SizeInRegs = (TI.
Width + 31) / 32;
827 SmallVector<llvm::Type*, 3> Elements(SizeInRegs, Int32);
828 llvm::Type *
Result = llvm::StructType::get(LLVMContext, Elements);
834 llvm::IntegerType *PaddingType = NeedsPadding ?
Int32 :
nullptr;
841 if (IsWin32StructABI && State.Required.
isRequiredArg(ArgIndex)) {
842 unsigned AlignInBits = 0;
844 const ASTRecordLayout &Layout =
845 getContext().getASTRecordLayout(RT->getDecl());
848 AlignInBits = TI.
Align;
850 if (AlignInBits > 32)
851 return getIndirectResult(Ty,
false, State);
860 if (TI.
Width <= 4 * 32 && (!IsMCUABI || State.FreeRegs == 0) &&
861 canExpandIndirectArgument(Ty))
863 IsFastCall || IsVectorCall || IsRegCall, PaddingType);
865 return getIndirectResult(Ty,
true, State);
868 if (
const VectorType *VT = Ty->
getAs<VectorType>()) {
872 if (IsWin32StructABI) {
873 if (TI.
Width <= 512 && State.FreeSSERegs > 0) {
877 return getIndirectResult(Ty,
false, State);
882 if (IsDarwinVectorABI) {
884 (TI.
Width == 64 && VT->getNumElements() == 1))
886 llvm::IntegerType::get(getVMContext(), TI.
Width));
889 if (IsX86_MMXType(CGT.ConvertType(Ty)))
896 Ty = ED->getIntegerType();
898 bool InReg = shouldPrimitiveUseInReg(Ty, State);
900 if (isPromotableIntegerTypeForABI(Ty)) {
906 if (
const auto *EIT = Ty->
getAs<BitIntType>()) {
907 if (EIT->getNumBits() <= 64) {
912 return getIndirectResult(Ty,
false, State);
920void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI)
const {
924 else if (State.CC == llvm::CallingConv::X86_FastCall) {
926 State.FreeSSERegs = 3;
927 }
else if (State.CC == llvm::CallingConv::X86_VectorCall) {
929 State.FreeSSERegs = 6;
932 else if (State.CC == llvm::CallingConv::X86_RegCall) {
934 State.FreeSSERegs = 8;
935 }
else if (IsWin32StructABI) {
938 State.FreeRegs = DefaultNumRegisterParameters;
939 State.FreeSSERegs = 3;
941 State.FreeRegs = DefaultNumRegisterParameters;
948 if (State.FreeRegs) {
961 if (State.CC == llvm::CallingConv::X86_VectorCall)
962 runVectorCallFirstPass(FI, State);
964 bool UsedInAlloca =
false;
965 MutableArrayRef<CGFunctionInfoArgInfo> Args = FI.
arguments();
966 for (
unsigned I = 0, E = Args.size(); I < E; ++I) {
968 if (State.IsPreassigned.test(I))
979 rewriteWithInAlloca(FI);
983X86_32ABIInfo::addFieldToArgStruct(SmallVector<llvm::Type *, 6> &FrameFields,
984 CharUnits &StackOffset, ABIArgInfo &Info,
985 QualType
Type)
const {
988 assert(StackOffset.
isMultipleOf(WordSize) &&
"unaligned inalloca struct");
993 bool IsIndirect =
false;
997 llvm::Type *LLTy = CGT.ConvertTypeForMem(
Type);
999 LLTy = llvm::PointerType::getUnqual(getVMContext());
1000 FrameFields.push_back(LLTy);
1001 StackOffset += IsIndirect ? WordSize : getContext().getTypeSizeInChars(
Type);
1004 CharUnits FieldEnd = StackOffset;
1005 StackOffset = FieldEnd.
alignTo(WordSize);
1006 if (StackOffset != FieldEnd) {
1007 CharUnits NumBytes = StackOffset - FieldEnd;
1008 llvm::Type *Ty = llvm::Type::getInt8Ty(getVMContext());
1009 Ty = llvm::ArrayType::get(Ty, NumBytes.
getQuantity());
1010 FrameFields.push_back(Ty);
1033 llvm_unreachable(
"invalid enum");
1036void X86_32ABIInfo::rewriteWithInAlloca(CGFunctionInfo &FI)
const {
1037 assert(IsWin32StructABI &&
"inalloca only supported on win32");
1040 SmallVector<llvm::Type *, 6> FrameFields;
1045 CharUnits StackOffset;
1052 if (
Ret.isIndirect() &&
Ret.isSRetAfterThis() && !IsThisCall &&
1054 addFieldToArgStruct(FrameFields, StackOffset, I->
info, I->
type);
1059 if (
Ret.isIndirect() && !
Ret.getInReg()) {
1060 addFieldToArgStruct(FrameFields, StackOffset, Ret, FI.
getReturnType());
1062 Ret.setInAllocaSRet(IsWin32StructABI);
1070 for (; I != E; ++I) {
1072 addFieldToArgStruct(FrameFields, StackOffset, I->
info, I->
type);
1075 FI.
setArgStruct(llvm::StructType::get(getVMContext(), FrameFields,
1080RValue X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
1081 QualType Ty, AggValueSlot Slot)
const {
1083 auto TypeInfo = getContext().getTypeInfoInChars(Ty);
1085 CCState State(*
const_cast<CGFunctionInfo *
>(CGF.
CurFnInfo));
1096 getTypeStackAlignInBytes(Ty, TypeInfo.Align.getQuantity()));
1103bool X86_32TargetCodeGenInfo::isStructReturnInRegABI(
1104 const llvm::Triple &Triple,
const CodeGenOptions &Opts) {
1105 assert(Triple.getArch() == llvm::Triple::x86);
1107 switch (Opts.getStructReturnConvention()) {
1116 if (Triple.isOSDarwin() || Triple.isOSIAMCU())
1119 switch (Triple.getOS()) {
1120 case llvm::Triple::DragonFly:
1121 case llvm::Triple::FreeBSD:
1122 case llvm::Triple::OpenBSD:
1123 case llvm::Triple::Win32:
1132 if (!FD->
hasAttr<AnyX86InterruptAttr>())
1136 Fn->setCallingConv(llvm::CallingConv::X86_INTR);
1142 llvm::Attribute NewAttr = llvm::Attribute::getWithByValType(
1143 Fn->getContext(), ByValTy);
1144 Fn->addParamAttr(0, NewAttr);
1147void X86_32TargetCodeGenInfo::setTargetAttributes(
1148 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM)
const {
1149 if (GV->isDeclaration())
1151 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
1152 if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
1154 Fn->addFnAttr(
"stackrealign");
1161bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable(
1162 CodeGen::CodeGenFunction &CGF,
1163 llvm::Value *Address)
const {
1164 CodeGen::CGBuilderTy &Builder = CGF.
Builder;
1166 llvm::Value *Four8 = llvm::ConstantInt::get(CGF.
Int8Ty, 4);
1177 llvm::Value *Sixteen8 = llvm::ConstantInt::get(CGF.
Int8Ty, 16);
1183 Builder.CreateAlignedStore(
1184 Four8, Builder.CreateConstInBoundsGEP1_32(CGF.
Int8Ty, Address, 9),
1190 llvm::Value *Twelve8 = llvm::ConstantInt::get(CGF.
Int8Ty, 12);
1205static unsigned getNativeVectorSizeForAVXABI(
X86AVXABILevel AVXLevel) {
1207 case X86AVXABILevel::AVX512:
1209 case X86AVXABILevel::AVX:
1211 case X86AVXABILevel::None:
1214 llvm_unreachable(
"Unknown AVXLevel");
1218class X86_64ABIInfo :
public ABIInfo {
1255 void postMerge(
unsigned AggregateSize,
Class &Lo,
Class &Hi)
const;
1283 void classify(QualType
T, uint64_t OffsetBase,
Class &Lo,
Class &Hi,
1284 bool isNamedArg,
bool IsRegCall =
false)
const;
1286 llvm::Type *GetByteVectorType(QualType Ty)
const;
1287 llvm::Type *GetSSETypeAtOffset(llvm::Type *IRType,
1288 unsigned IROffset, QualType SourceTy,
1289 unsigned SourceOffset)
const;
1290 llvm::Type *GetINTEGERTypeAtOffset(llvm::Type *IRType,
1291 unsigned IROffset, QualType SourceTy,
1292 unsigned SourceOffset)
const;
1296 ABIArgInfo getIndirectReturnResult(QualType Ty)
const;
1303 ABIArgInfo getIndirectResult(QualType Ty,
unsigned freeIntRegs)
const;
1308 unsigned &neededInt,
unsigned &neededSSE,
1310 bool IsRegCall =
false)
const;
1312 ABIArgInfo classifyRegCallStructType(QualType Ty,
unsigned &NeededInt,
1313 unsigned &NeededSSE,
1314 unsigned &MaxVectorWidth)
const;
1316 bool passRegCallStructTypeDirectly(QualType Ty,
1317 SmallVectorImpl<llvm::Type *> &CoerceElts,
1318 unsigned &NeededInt,
unsigned &NeededSSE,
1319 unsigned &MaxVectorWidth)
const;
1321 bool IsIllegalVectorType(QualType Ty)
const;
1328 bool honorsRevision0_98()
const {
1329 return !getTarget().getTriple().isOSDarwin();
1334 bool classifyIntegerMMXAsSSE()
const {
1336 if (getContext().getLangOpts().isCompatibleWith(
1337 LangOptions::ClangABI::Ver3_8))
1340 const llvm::Triple &Triple = getTarget().getTriple();
1341 if (Triple.isOSDarwin() || Triple.isPS() || Triple.isOSFreeBSD())
1347 bool passInt128VectorsInMem()
const {
1349 if (getContext().getLangOpts().isCompatibleWith(
1350 LangOptions::ClangABI::Ver9))
1353 const llvm::Triple &
T = getTarget().getTriple();
1354 return T.isOSLinux() ||
T.isOSNetBSD();
1357 bool returnCXXRecordGreaterThan128InMem()
const {
1359 if (getContext().getLangOpts().isCompatibleWith(
1360 LangOptions::ClangABI::Ver20) ||
1370 bool Has64BitPointers;
1373 X86_64ABIInfo(CodeGen::CodeGenTypes &CGT,
X86AVXABILevel AVXLevel)
1374 : ABIInfo(CGT), AVXLevel(AVXLevel),
1375 Has64BitPointers(CGT.getDataLayout().getPointerSize(0) == 8) {}
1377 bool isPassedUsingAVXType(QualType
type)
const {
1378 unsigned neededInt, neededSSE;
1382 if (
info.isDirect()) {
1383 llvm::Type *ty =
info.getCoerceToType();
1384 if (llvm::VectorType *vectorTy = dyn_cast_or_null<llvm::VectorType>(ty))
1385 return vectorTy->getPrimitiveSizeInBits().getFixedValue() > 128;
1390 void computeInfo(CGFunctionInfo &FI)
const override;
1391 unsigned getX86ABIAVXLevel(
const FunctionDecl *FD,
1392 const FunctionType::ExtInfo &Info)
const override;
1394 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
1395 AggValueSlot Slot)
const override;
1396 RValue EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
1397 AggValueSlot Slot)
const override;
1399 bool has64BitPointers()
const {
1400 return Has64BitPointers;
1405class WinX86_64ABIInfo :
public ABIInfo {
1407 WinX86_64ABIInfo(CodeGen::CodeGenTypes &CGT,
X86AVXABILevel AVXLevel)
1408 : ABIInfo(CGT), AVXLevel(AVXLevel),
1409 IsMingw64(getTarget().
getTriple().isWindowsGNUEnvironment()) {}
1411 void computeInfo(CGFunctionInfo &FI)
const override;
1412 unsigned getX86ABIAVXLevel(
const FunctionDecl *FD,
1413 const FunctionType::ExtInfo &Info)
const override;
1415 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
1416 AggValueSlot Slot)
const override;
1418 bool isHomogeneousAggregateBaseType(QualType Ty)
const override {
1420 return isX86VectorTypeForVectorCall(getContext(), Ty);
1423 bool isHomogeneousAggregateSmallEnough(
const Type *Ty,
1424 uint64_t NumMembers)
const override {
1426 return isX86VectorCallAggregateSmallEnough(NumMembers);
1429 ABIArgInfo classifyArgForArm64ECVarArg(QualType Ty,
1430 bool IsNamedArg)
const override {
1431 unsigned FreeSSERegs = 0;
1433 IsNamedArg ? ClassifyKind::FixedArgument : ClassifyKind::VarArg;
1434 return classify(Ty, FreeSSERegs, Kind, llvm::CallingConv::C);
1438 enum class ClassifyKind { Return, FixedArgument, VarArg };
1440 ABIArgInfo classify(QualType Ty,
unsigned &FreeSSERegs, ClassifyKind Kind,
1442 ABIArgInfo reclassifyHvaArgForVectorCall(QualType Ty,
unsigned &FreeSSERegs,
1443 const ABIArgInfo ¤t)
const;
1450class X86_64TargetCodeGenInfo :
public TargetCodeGenInfo {
1452 X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
X86AVXABILevel AVXLevel)
1453 : TargetCodeGenInfo(std::make_unique<X86_64ABIInfo>(CGT, AVXLevel)) {
1455 std::make_unique<SwiftABIInfo>(CGT,
true);
1460 bool markARCOptimizedReturnCallsAsNoTail()
const override {
return true; }
1462 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM)
const override {
1466 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
1467 llvm::Value *Address)
const override {
1468 llvm::Value *Eight8 = llvm::ConstantInt::get(CGF.
Int8Ty, 8);
1476 llvm::Type* adjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
1477 StringRef Constraint,
1478 llvm::Type* Ty)
const override {
1479 return X86AdjustInlineAsmType(CGF, Constraint, Ty);
1482 bool isNoProtoCallVariadic(
const CallArgList &args,
1483 const FunctionNoProtoType *fnType)
const override {
1491 bool HasAVXType =
false;
1492 for (
const CallArg &arg : args) {
1493 if (getABIInfo<X86_64ABIInfo>().isPassedUsingAVXType(
arg.Ty)) {
1506 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1507 CodeGen::CodeGenModule &CGM)
const override {
1508 if (GV->isDeclaration())
1510 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
1511 if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
1513 Fn->addFnAttr(
"stackrealign");
1520 void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc,
1521 const FunctionDecl *Caller,
1522 const FunctionDecl *Callee,
const CallArgList &Args,
1523 QualType ReturnType)
const override;
1525 void checkFunctionABI(CodeGenModule &CGM,
1526 const FunctionDecl *FD)
const override;
1531 llvm::StringMap<bool> &CallerMap,
1533 llvm::StringMap<bool> &CalleeMap,
1535 if (CalleeMap.empty() && CallerMap.empty()) {
1547 const llvm::StringMap<bool> &CallerMap,
1548 const llvm::StringMap<bool> &CalleeMap,
1551 bool CallerHasFeat = CallerMap.lookup(
Feature);
1552 bool CalleeHasFeat = CalleeMap.lookup(
Feature);
1554 if (!CallerHasFeat && !CalleeHasFeat &&
1555 (!Callee.isExternallyVisible() || Callee.hasAttr<AlwaysInlineAttr>()))
1558 if (!CallerHasFeat && !CalleeHasFeat)
1559 return Diag.Report(CallLoc, diag::warn_avx_calling_convention)
1560 << IsArgument << Ty <<
Feature;
1563 if (!CallerHasFeat || !CalleeHasFeat)
1564 return Diag.Report(CallLoc, diag::err_avx_calling_convention)
1565 << IsArgument << Ty <<
Feature;
1574 const llvm::StringMap<bool> &CallerMap,
1575 const llvm::StringMap<bool> &CalleeMap,
QualType Ty,
1580 "avx512f", IsArgument);
1589void X86_64TargetCodeGenInfo::checkFunctionABI(CodeGenModule &CGM,
1590 const FunctionDecl *FD)
const {
1591 auto GetReturnTypeLoc = [](
const FunctionDecl *FD) {
1593 TypeLoc TL = TSI->getTypeLoc();
1596 SourceLocation Loc = FTL.getReturnLoc().getBeginLoc();
1609 auto Check = [&](QualType Ty, SourceLocation Loc,
bool IsReturn) {
1618 llvm::StringMap<bool> FeatureMap;
1620 if (!FeatureMap.lookup(
Feature)) {
1622 << !IsReturn << Ty <<
Feature;
1639 for (
const ParmVarDecl *P : FD->
parameters()) {
1640 SourceLocation Loc = P->getLocation();
1642 Loc = P->getBeginLoc();
1643 if (Check(P->getType(), Loc,
false))
1648void X86_64TargetCodeGenInfo::checkFunctionCallABI(CodeGenModule &CGM,
1649 SourceLocation CallLoc,
1650 const FunctionDecl *Caller,
1651 const FunctionDecl *Callee,
1652 const CallArgList &Args,
1653 QualType ReturnType)
const {
1657 llvm::StringMap<bool> CallerMap;
1658 llvm::StringMap<bool> CalleeMap;
1659 unsigned ArgIndex = 0;
1663 for (
const CallArg &Arg : Args) {
1671 if (Arg.getType()->isVectorType() &&
1674 QualType Ty = Arg.getType();
1677 if (ArgIndex < Callee->getNumParams())
1678 Ty =
Callee->getParamDecl(ArgIndex)->getType();
1681 CallerMap, CalleeMap, Ty,
true))
1689 if (
Callee->getReturnType()->isVectorType() &&
1693 CalleeMap,
Callee->getReturnType(),
1702 bool Quote = Lib.contains(
' ');
1703 std::string ArgStr = Quote ?
"\"" :
"";
1705 if (!Lib.ends_with_insensitive(
".lib") && !Lib.ends_with_insensitive(
".a"))
1707 ArgStr += Quote ?
"\"" :
"";
1712class WinX86_32TargetCodeGenInfo :
public X86_32TargetCodeGenInfo {
1715 bool DarwinVectorABI,
bool RetSmallStructInRegABI,
bool Win32StructABI,
1716 unsigned NumRegisterParameters)
1717 : X86_32TargetCodeGenInfo(CGT, DarwinVectorABI, RetSmallStructInRegABI,
1718 Win32StructABI, NumRegisterParameters,
false) {}
1720 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1723 void getDependentLibraryOption(llvm::StringRef Lib,
1725 Opt =
"/DEFAULTLIB:";
1726 Opt += qualifyWindowsLibrary(Lib);
1729 void getDetectMismatchOption(llvm::StringRef Name,
1730 llvm::StringRef
Value,
1732 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
1737void WinX86_32TargetCodeGenInfo::setTargetAttributes(
1738 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM)
const {
1739 X86_32TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
1740 if (GV->isDeclaration())
1742 addStackProbeTargetAttributes(D, GV, CGM);
1746class WinX86_64TargetCodeGenInfo :
public TargetCodeGenInfo {
1748 WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
1750 : TargetCodeGenInfo(std::make_unique<WinX86_64ABIInfo>(CGT, AVXLevel)) {
1752 std::make_unique<SwiftABIInfo>(CGT,
true);
1755 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1756 CodeGen::CodeGenModule &CGM)
const override;
1758 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM)
const override {
1762 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
1763 llvm::Value *Address)
const override {
1764 llvm::Value *Eight8 = llvm::ConstantInt::get(CGF.
Int8Ty, 8);
1772 void getDependentLibraryOption(llvm::StringRef Lib,
1773 llvm::SmallString<24> &Opt)
const override {
1774 Opt =
"/DEFAULTLIB:";
1775 Opt += qualifyWindowsLibrary(Lib);
1778 void getDetectMismatchOption(llvm::StringRef Name,
1779 llvm::StringRef
Value,
1780 llvm::SmallString<32> &Opt)
const override {
1781 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
1786void WinX86_64TargetCodeGenInfo::setTargetAttributes(
1787 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM)
const {
1789 if (GV->isDeclaration())
1791 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
1792 if (FD->
hasAttr<X86ForceAlignArgPointerAttr>()) {
1794 Fn->addFnAttr(
"stackrealign");
1800 addStackProbeTargetAttributes(D, GV, CGM);
1803void X86_64ABIInfo::postMerge(
unsigned AggregateSize,
Class &Lo,
1828 if (Hi == X87Up && Lo != X87 && honorsRevision0_98())
1830 if (AggregateSize > 128 && (Lo != SSE || Hi != SSEUp))
1832 if (Hi == SSEUp && Lo != SSE)
1842 LangOptions::ClangABI::Ver23) {
1843 return GlobalAVXLevel;
1850 if (!FD || !FD->
hasAttr<TargetAttr>())
1853 llvm::StringMap<bool> FeatureMap;
1855 if (FeatureMap.lookup(
"avx512f"))
1857 if (FeatureMap.lookup(
"avx"))
1862X86_64ABIInfo::Class X86_64ABIInfo::merge(
Class Accum,
Class Field) {
1886 assert((Accum != Memory && Accum != ComplexX87) &&
1887 "Invalid accumulated classification during merge.");
1888 if (Accum == Field || Field == NoClass)
1890 if (Field == Memory)
1892 if (Accum == NoClass)
1896 if (Field == X87 || Field == X87Up || Field == ComplexX87 ||
1897 Accum == X87 || Accum == X87Up)
1902void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
Class &Lo,
1903 Class &Hi,
bool isNamedArg,
bool IsRegCall)
const {
1914 Class &Current = OffsetBase < 64 ? Lo : Hi;
1917 if (
const BuiltinType *BT = Ty->
getAs<BuiltinType>()) {
1920 if (k == BuiltinType::Void) {
1922 }
else if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
1925 }
else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
1927 }
else if (k == BuiltinType::Float || k == BuiltinType::Double ||
1928 k == BuiltinType::Float16 || k == BuiltinType::BFloat16) {
1930 }
else if (k == BuiltinType::Float128) {
1933 }
else if (k == BuiltinType::LongDouble) {
1934 const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
1935 if (LDF == &llvm::APFloat::IEEEquad()) {
1938 }
else if (LDF == &llvm::APFloat::x87DoubleExtended()) {
1941 }
else if (LDF == &llvm::APFloat::IEEEdouble()) {
1944 llvm_unreachable(
"unexpected long double representation!");
1953 classify(ED->getIntegerType(), OffsetBase, Lo, Hi, isNamedArg);
1964 if (Has64BitPointers) {
1971 uint64_t EB_FuncPtr = (OffsetBase) / 64;
1972 uint64_t EB_ThisAdj = (OffsetBase + 64 - 1) / 64;
1973 if (EB_FuncPtr != EB_ThisAdj) {
1985 if (
const VectorType *VT = Ty->
getAs<VectorType>()) {
1987 if (Size == 1 || Size == 8 || Size == 16 || Size == 32) {
1996 uint64_t EB_Lo = (OffsetBase) / 64;
2000 }
else if (Size == 64) {
2001 QualType ElementType = VT->getElementType();
2004 if (ElementType->isSpecificBuiltinType(BuiltinType::Double))
2010 if (!classifyIntegerMMXAsSSE() &&
2011 (ElementType->isSpecificBuiltinType(BuiltinType::LongLong) ||
2012 ElementType->isSpecificBuiltinType(BuiltinType::ULongLong) ||
2013 ElementType->isSpecificBuiltinType(BuiltinType::Long) ||
2014 ElementType->isSpecificBuiltinType(BuiltinType::ULong)))
2021 if (OffsetBase && OffsetBase != 64)
2023 }
else if (Size == 128 ||
2024 (isNamedArg && Size <= getNativeVectorSizeForAVXABI(AVXLevel))) {
2025 QualType ElementType = VT->getElementType();
2028 if (passInt128VectorsInMem() && Size != 128 &&
2029 (ElementType->isSpecificBuiltinType(BuiltinType::Int128) ||
2030 ElementType->isSpecificBuiltinType(BuiltinType::UInt128)))
2053 if (
const ComplexType *CT = Ty->
getAs<ComplexType>()) {
2060 else if (Size <= 128)
2062 }
else if (ET->
isFloat16Type() || ET == getContext().FloatTy ||
2065 }
else if (ET == getContext().DoubleTy) {
2067 }
else if (ET == getContext().LongDoubleTy) {
2068 const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
2069 if (LDF == &llvm::APFloat::IEEEquad())
2071 else if (LDF == &llvm::APFloat::x87DoubleExtended())
2072 Current = ComplexX87;
2073 else if (LDF == &llvm::APFloat::IEEEdouble())
2076 llvm_unreachable(
"unexpected long double representation!");
2081 uint64_t EB_Real = (OffsetBase) / 64;
2082 uint64_t EB_Imag = (OffsetBase + getContext().getTypeSize(ET)) / 64;
2083 if (Hi == NoClass && EB_Real != EB_Imag)
2089 if (
const auto *EITy = Ty->
getAs<BitIntType>()) {
2090 if (EITy->getNumBits() <= 64)
2092 else if (EITy->getNumBits() <= 128)
2098 if (
const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
2107 if (!IsRegCall && Size > 512)
2114 if (OffsetBase % getContext().getTypeAlign(AT->getElementType()))
2120 uint64_t EltSize = getContext().getTypeSize(AT->getElementType());
2121 uint64_t ArraySize = AT->getZExtSize();
2128 (Size != EltSize || Size > getNativeVectorSizeForAVXABI(AVXLevel)))
2131 for (uint64_t i=0, Offset=OffsetBase; i<ArraySize; ++i, Offset += EltSize) {
2132 Class FieldLo, FieldHi;
2133 classify(AT->getElementType(), Offset, FieldLo, FieldHi, isNamedArg);
2134 Lo =
merge(Lo, FieldLo);
2135 Hi =
merge(Hi, FieldHi);
2136 if (Lo == Memory || Hi == Memory)
2140 postMerge(Size, Lo, Hi);
2141 assert((Hi != SSEUp || Lo == SSE) &&
"Invalid SSEUp array classification.");
2165 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
2171 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2172 for (
const auto &I : CXXRD->bases()) {
2173 assert(!I.isVirtual() && !I.getType()->isDependentType() &&
2174 "Unexpected base class!");
2175 const auto *
Base = I.getType()->castAsCXXRecordDecl();
2181 Class FieldLo, FieldHi;
2184 classify(I.getType(), Offset, FieldLo, FieldHi, isNamedArg);
2185 Lo =
merge(Lo, FieldLo);
2186 Hi =
merge(Hi, FieldHi);
2187 if (returnCXXRecordGreaterThan128InMem() &&
2189 (Size > 128 && (Size != getContext().getTypeSize(I.getType()) ||
2190 Size > getNativeVectorSizeForAVXABI(AVXLevel)))) {
2195 if (Lo == Memory || Hi == Memory) {
2196 postMerge(Size, Lo, Hi);
2204 bool UseClang11Compat = getContext().getLangOpts().isCompatibleWith(
2205 LangOptions::ClangABI::Ver11) ||
2206 getContext().getTargetInfo().getTriple().isPS();
2207 bool ClassifyUnnamedBitFields =
2208 getContext().getLangOpts().getClangABICompat() >
2209 LangOptions::ClangABI::Ver23 &&
2210 !getContext().getTargetInfo().getTriple().isPS();
2211 bool IsUnion = RT->isUnionType() && !UseClang11Compat;
2214 i != e; ++i, ++idx) {
2216 bool BitField = i->isBitField();
2223 if (BitField && (ClassifyUnnamedBitFields ? i->isZeroLengthBitField()
2224 : i->isUnnamedBitField()))
2237 ((!IsUnion && Size != getContext().getTypeSize(i->getType())) ||
2238 Size > getNativeVectorSizeForAVXABI(AVXLevel))) {
2240 postMerge(Size, Lo, Hi);
2245 Offset % getContext().getTypeAlign(i->getType().getCanonicalType());
2247 if (!BitField && IsInMemory) {
2249 postMerge(Size, Lo, Hi);
2259 Class FieldLo, FieldHi;
2265 assert(ClassifyUnnamedBitFields ? !i->isZeroLengthBitField()
2266 : !i->isUnnamedBitField());
2274 assert(EB_Hi == EB_Lo &&
"Invalid classification, type > 16 bytes.");
2279 FieldHi = EB_Hi ?
Integer : NoClass;
2282 classify(i->getType(), Offset, FieldLo, FieldHi, isNamedArg);
2283 Lo =
merge(Lo, FieldLo);
2284 Hi =
merge(Hi, FieldHi);
2285 if (Lo == Memory || Hi == Memory)
2289 postMerge(Size, Lo, Hi);
2293ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty)
const {
2299 Ty = ED->getIntegerType();
2302 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
2304 llvm::Type *IRTy = CGT.ConvertType(Ty);
2309 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
2312bool X86_64ABIInfo::IsIllegalVectorType(QualType Ty)
const {
2313 if (
const VectorType *VecTy = Ty->
getAs<VectorType>()) {
2315 unsigned LargestVector = getNativeVectorSizeForAVXABI(AVXLevel);
2316 if (Size <= 64 || Size > LargestVector)
2318 QualType EltTy = VecTy->getElementType();
2319 if (passInt128VectorsInMem() &&
2328ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty,
2329 unsigned freeIntRegs)
const {
2342 Ty = ED->getIntegerType();
2344 llvm::Type *IRTy = CGT.ConvertType(Ty);
2350 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
2355 unsigned Align = std::max(getContext().getTypeAlign(Ty) / 8, 8U);
2378 if (freeIntRegs == 0) {
2383 if (Align == 8 && Size <= 64)
2389 getDataLayout().getAllocaAddrSpace());
2394llvm::Type *X86_64ABIInfo::GetByteVectorType(QualType Ty)
const {
2398 Ty = QualType(InnerTy, 0);
2400 llvm::Type *IRType = CGT.ConvertType(Ty);
2404 if (passInt128VectorsInMem() &&
2408 return llvm::FixedVectorType::get(llvm::Type::getInt64Ty(getVMContext()),
2415 if (IRType->getTypeID() == llvm::Type::FP128TyID)
2420 assert((Size == 128 || Size == 256 || Size == 512) &&
"Invalid type found!");
2424 return llvm::FixedVectorType::get(llvm::Type::getDoubleTy(getVMContext()),
2440 unsigned TySize = (
unsigned)Context.getTypeSize(Ty);
2441 if (TySize <= StartBit)
2445 unsigned EltSize = (
unsigned)Context.getTypeSize(AT->getElementType());
2446 unsigned NumElts = (
unsigned)AT->getZExtSize();
2449 for (
unsigned i = 0; i != NumElts; ++i) {
2451 unsigned EltOffset = i*EltSize;
2452 if (EltOffset >= EndBit)
break;
2454 unsigned EltStart = EltOffset < StartBit ? StartBit-EltOffset :0;
2456 EndBit-EltOffset, Context))
2467 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2468 for (
const auto &I : CXXRD->bases()) {
2469 assert(!I.isVirtual() && !I.getType()->isDependentType() &&
2470 "Unexpected base class!");
2471 const auto *
Base = I.getType()->castAsCXXRecordDecl();
2475 if (BaseOffset >= EndBit)
continue;
2477 unsigned BaseStart = BaseOffset < StartBit ? StartBit-BaseOffset :0;
2479 EndBit-BaseOffset, Context))
2490 i != e; ++i, ++idx) {
2494 if (FieldOffset >= EndBit)
break;
2496 unsigned FieldStart = FieldOffset < StartBit ? StartBit-FieldOffset :0;
2512 const llvm::DataLayout &TD) {
2513 if (IROffset == 0 && IRType->isFloatingPointTy())
2517 if (llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) {
2518 if (!STy->getNumContainedTypes())
2521 const llvm::StructLayout *SL = TD.getStructLayout(STy);
2522 unsigned Elt = SL->getElementContainingOffset(IROffset);
2523 IROffset -= SL->getElementOffset(Elt);
2528 if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) {
2529 llvm::Type *EltTy = ATy->getElementType();
2530 unsigned EltSize = TD.getTypeAllocSize(EltTy);
2531 IROffset -= IROffset / EltSize * EltSize;
2540llvm::Type *X86_64ABIInfo::
2541GetSSETypeAtOffset(llvm::Type *IRType,
unsigned IROffset,
2542 QualType SourceTy,
unsigned SourceOffset)
const {
2543 const llvm::DataLayout &TD = getDataLayout();
2544 unsigned SourceSize =
2545 (unsigned)getContext().getTypeSize(SourceTy) / 8 - SourceOffset;
2547 if (!T0 || T0->isDoubleTy())
2548 return llvm::Type::getDoubleTy(getVMContext());
2551 llvm::Type *T1 =
nullptr;
2552 unsigned T0Size = TD.getTypeAllocSize(T0);
2553 if (SourceSize > T0Size)
2555 if (T1 ==
nullptr) {
2558 if (T0->is16bitFPTy() && SourceSize > 4)
2567 if (T0->isFloatTy() && T1->isFloatTy())
2568 return llvm::FixedVectorType::get(T0, 2);
2570 if (T0->is16bitFPTy() && T1->is16bitFPTy()) {
2571 llvm::Type *T2 =
nullptr;
2575 return llvm::FixedVectorType::get(T0, 2);
2576 return llvm::FixedVectorType::get(T0, 4);
2579 if (T0->is16bitFPTy() || T1->is16bitFPTy())
2580 return llvm::FixedVectorType::get(llvm::Type::getHalfTy(getVMContext()), 4);
2582 return llvm::Type::getDoubleTy(getVMContext());
2599llvm::Type *X86_64ABIInfo::
2600GetINTEGERTypeAtOffset(llvm::Type *IRType,
unsigned IROffset,
2601 QualType SourceTy,
unsigned SourceOffset)
const {
2604 if (IROffset == 0) {
2607 IRType->isIntegerTy(64))
2616 if (IRType->isIntegerTy(8) || IRType->isIntegerTy(16) ||
2617 IRType->isIntegerTy(32) ||
2623 SourceOffset*8+64, getContext()))
2628 if (llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) {
2630 const llvm::StructLayout *SL = getDataLayout().getStructLayout(STy);
2631 if (IROffset < SL->getSizeInBytes()) {
2632 unsigned FieldIdx = SL->getElementContainingOffset(IROffset);
2633 IROffset -= SL->getElementOffset(FieldIdx);
2635 return GetINTEGERTypeAtOffset(STy->getElementType(FieldIdx), IROffset,
2636 SourceTy, SourceOffset);
2640 if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) {
2641 llvm::Type *EltTy = ATy->getElementType();
2642 unsigned EltSize = getDataLayout().getTypeAllocSize(EltTy);
2643 unsigned EltOffset = IROffset/EltSize*EltSize;
2644 return GetINTEGERTypeAtOffset(EltTy, IROffset-EltOffset, SourceTy,
2650 if (IRType->isIntegerTy(128)) {
2651 assert(IROffset == 0);
2657 unsigned TySizeInBytes =
2658 (unsigned)getContext().getTypeSizeInChars(SourceTy).getQuantity();
2660 assert(TySizeInBytes != SourceOffset &&
"Empty field?");
2664 return llvm::IntegerType::get(getVMContext(),
2665 std::min(TySizeInBytes-SourceOffset, 8U)*8);
2676 const llvm::DataLayout &TD) {
2681 unsigned LoSize = (
unsigned)TD.getTypeAllocSize(Lo);
2682 llvm::Align HiAlign = TD.getABITypeAlign(Hi);
2683 unsigned HiStart = llvm::alignTo(LoSize, HiAlign);
2684 assert(HiStart != 0 && HiStart <= 8 &&
"Invalid x86-64 argument pair!");
2695 if (Lo->isHalfTy() || Lo->isFloatTy())
2696 Lo = llvm::Type::getDoubleTy(Lo->getContext());
2698 assert((Lo->isIntegerTy() || Lo->isPointerTy())
2699 &&
"Invalid/unknown lo type");
2700 Lo = llvm::Type::getInt64Ty(Lo->getContext());
2704 llvm::StructType *
Result = llvm::StructType::get(Lo, Hi);
2707 assert(TD.getStructLayout(
Result)->getElementOffset(1) == 8 &&
2708 "Invalid x86-64 argument pair!");
2712ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy)
const {
2715 X86_64ABIInfo::Class Lo, Hi;
2716 classify(RetTy, 0, Lo, Hi,
true);
2719 assert((Hi != Memory || Lo == Memory) &&
"Invalid memory classification.");
2720 assert((Hi != SSEUp || Lo == SSE) &&
"Invalid SSEUp classification.");
2722 llvm::Type *ResType =
nullptr;
2729 assert((Hi == SSE || Hi ==
Integer || Hi == X87Up) &&
2730 "Unknown missing lo part");
2735 llvm_unreachable(
"Invalid classification for lo word.");
2740 return getIndirectReturnResult(RetTy);
2745 ResType = GetINTEGERTypeAtOffset(CGT.ConvertType(RetTy), 0, RetTy, 0);
2752 RetTy = ED->getIntegerType();
2755 isPromotableIntegerTypeForABI(RetTy))
2759 if (ResType->isIntegerTy(128)) {
2769 ResType = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 0, RetTy, 0);
2775 ResType = llvm::Type::getX86_FP80Ty(getVMContext());
2782 assert(Hi == ComplexX87 &&
"Unexpected ComplexX87 classification.");
2783 ResType = llvm::StructType::get(llvm::Type::getX86_FP80Ty(getVMContext()),
2784 llvm::Type::getX86_FP80Ty(getVMContext()));
2788 llvm::Type *HighPart =
nullptr;
2794 llvm_unreachable(
"Invalid classification for hi word.");
2801 HighPart = GetINTEGERTypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8);
2806 HighPart = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8);
2817 assert(Lo == SSE &&
"Unexpected SSEUp classification.");
2818 ResType = GetByteVectorType(RetTy);
2829 HighPart = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8);
2846X86_64ABIInfo::classifyArgumentType(QualType Ty,
unsigned freeIntRegs,
2847 unsigned &neededInt,
unsigned &neededSSE,
2848 bool isNamedArg,
bool IsRegCall)
const {
2851 X86_64ABIInfo::Class Lo, Hi;
2852 classify(Ty, 0, Lo, Hi, isNamedArg, IsRegCall);
2856 assert((Hi != Memory || Lo == Memory) &&
"Invalid memory classification.");
2857 assert((Hi != SSEUp || Lo == SSE) &&
"Invalid SSEUp classification.");
2861 llvm::Type *ResType =
nullptr;
2868 assert((Hi == SSE || Hi ==
Integer || Hi == X87Up) &&
2869 "Unknown missing lo part");
2882 return getIndirectResult(Ty, freeIntRegs);
2886 llvm_unreachable(
"Invalid classification for lo word.");
2895 ResType = GetINTEGERTypeAtOffset(CGT.ConvertType(Ty), 0, Ty, 0);
2902 Ty = ED->getIntegerType();
2905 isPromotableIntegerTypeForABI(Ty))
2909 if (ResType->isIntegerTy(128)) {
2920 llvm::Type *IRType = CGT.ConvertType(Ty);
2921 ResType = GetSSETypeAtOffset(IRType, 0, Ty, 0);
2927 llvm::Type *HighPart =
nullptr;
2935 llvm_unreachable(
"Invalid classification for hi word.");
2937 case NoClass:
break;
2942 HighPart = GetINTEGERTypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8);
2953 HighPart = GetSSETypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8);
2963 assert(Lo == SSE &&
"Unexpected SSEUp classification");
2964 ResType = GetByteVectorType(Ty);
2981bool X86_64ABIInfo::passRegCallStructTypeDirectly(
2982 QualType Ty, SmallVectorImpl<llvm::Type *> &CoerceElts,
unsigned &NeededInt,
2983 unsigned &NeededSSE,
unsigned &MaxVectorWidth)
const {
2991 if (
auto CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2992 if (CXXRD->isDynamicClass())
2995 for (
const auto &I : CXXRD->bases()) {
2996 QualType BaseTy = I.getType();
2999 if (!passRegCallStructTypeDirectly(BaseTy, CoerceElts, NeededInt,
3000 NeededSSE, MaxVectorWidth))
3006 for (
const auto *FD : RD->
fields()) {
3011 if (!passRegCallStructTypeDirectly(MTy, CoerceElts, NeededInt, NeededSSE,
3017 const auto *AT = getContext().getAsConstantArrayType(MTy);
3019 MTy = AT->getElementType();
3021 unsigned LocalNeededInt, LocalNeededSSE;
3023 LocalNeededSSE,
true,
true);
3030 assert(CoerceTy &&
"ABI info for struct member has no coerce type");
3032 uint64_t NumElts = AT->getZExtSize();
3033 LocalNeededInt *= NumElts;
3034 LocalNeededSSE *= NumElts;
3035 CoerceElts.push_back(llvm::ArrayType::get(CoerceTy, NumElts));
3037 CoerceElts.push_back(CoerceTy);
3040 if (
const auto *VT = MTy->
getAs<VectorType>())
3041 if (getContext().getTypeSize(VT) > MaxVectorWidth)
3042 MaxVectorWidth = getContext().getTypeSize(VT);
3044 NeededInt += LocalNeededInt;
3045 NeededSSE += LocalNeededSSE;
3052X86_64ABIInfo::classifyRegCallStructType(QualType Ty,
unsigned &NeededInt,
3053 unsigned &NeededSSE,
3054 unsigned &MaxVectorWidth)
const {
3062 SmallVector<llvm::Type *, 16> CoerceElts;
3063 if (!passRegCallStructTypeDirectly(Ty, CoerceElts, NeededInt, NeededSSE,
3065 NeededInt = NeededSSE = 0;
3066 return getIndirectReturnResult(Ty);
3069 assert(!CoerceElts.empty() &&
"Non-empty struct produced no element types");
3071 llvm::StructType::get(getVMContext(), CoerceElts));
3075X86_64ABIInfo::getX86ABIAVXLevel(
const FunctionDecl *FD,
3076 const FunctionType::ExtInfo &Info)
const {
3080void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI)
const {
3086 WinX86_64ABIInfo Win64ABIInfo(CGT, AVXLevel);
3087 Win64ABIInfo.computeInfo(FI);
3092 static_cast<unsigned>(X86AVXABILevel::AVX512) &&
3093 "Unexpected X86 AVX ABI level");
3096 if (EffectiveAVXLevel != AVXLevel) {
3097 X86_64ABIInfo EffectiveABIInfo(CGT, EffectiveAVXLevel);
3098 EffectiveABIInfo.computeInfo(FI);
3102 bool IsRegCall =
CallingConv == llvm::CallingConv::X86_RegCall;
3105 unsigned FreeIntRegs = IsRegCall ? 11 : 6;
3106 unsigned FreeSSERegs = IsRegCall ? 16 : 8;
3107 unsigned NeededInt = 0, NeededSSE = 0, MaxVectorWidth = 0;
3114 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
3115 FreeIntRegs -= NeededInt;
3116 FreeSSERegs -= NeededSSE;
3122 ->
getAs<ComplexType>()
3123 ->getElementType()) ==
3124 getContext().LongDoubleTy)
3136 else if (NeededSSE && MaxVectorWidth > 0)
3152 it != ie; ++it, ++ArgNo) {
3153 bool IsNamedArg = ArgNo < NumRequiredArgs;
3155 if (IsRegCall && it->type->isStructureOrClassType())
3156 it->info = classifyRegCallStructType(it->type, NeededInt, NeededSSE,
3160 NeededSSE, IsNamedArg);
3166 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
3167 FreeIntRegs -= NeededInt;
3168 FreeSSERegs -= NeededSSE;
3172 it->info = getIndirectResult(it->type, FreeIntRegs);
3181 llvm::Value *overflow_arg_area =
3196 llvm::Value *Res = overflow_arg_area;
3203 uint64_t SizeInBytes = (CGF.
getContext().getTypeSize(Ty) + 7) / 8;
3204 llvm::Value *Offset =
3205 llvm::ConstantInt::get(CGF.
Int32Ty, (SizeInBytes + 7) & ~7);
3207 Offset,
"overflow_arg_area.next");
3211 return Address(Res, LTy, Align);
3214RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
3215 QualType Ty, AggValueSlot Slot)
const {
3223 unsigned neededInt, neededSSE;
3235 if (!neededInt && !neededSSE)
3251 llvm::Value *InRegs =
nullptr;
3253 llvm::Value *gp_offset =
nullptr, *fp_offset =
nullptr;
3257 InRegs = llvm::ConstantInt::get(CGF.
Int32Ty, 48 - neededInt * 8);
3258 InRegs = CGF.
Builder.CreateICmpULE(gp_offset, InRegs,
"fits_in_gp");
3264 llvm::Value *FitsInFP =
3265 llvm::ConstantInt::get(CGF.
Int32Ty, 176 - neededSSE * 16);
3266 FitsInFP = CGF.
Builder.CreateICmpULE(fp_offset, FitsInFP,
"fits_in_fp");
3267 InRegs = InRegs ? CGF.
Builder.CreateAnd(InRegs, FitsInFP) : FitsInFP;
3273 CGF.
Builder.CreateCondBr(InRegs, InRegBlock, InMemBlock);
3294 if (neededInt && neededSSE) {
3296 assert(AI.
isDirect() &&
"Unexpected ABI info for mixed regs");
3300 assert(ST->getNumElements() == 2 &&
"Unexpected ABI info for mixed regs");
3301 llvm::Type *TyLo = ST->getElementType(0);
3302 llvm::Type *TyHi = ST->getElementType(1);
3303 assert((TyLo->isFPOrFPVectorTy() ^ TyHi->isFPOrFPVectorTy()) &&
3304 "Unexpected ABI info for mixed regs");
3305 llvm::Value *GPAddr =
3307 llvm::Value *FPAddr =
3309 llvm::Value *RegLoAddr = TyLo->isFPOrFPVectorTy() ? FPAddr : GPAddr;
3310 llvm::Value *RegHiAddr = TyLo->isFPOrFPVectorTy() ? GPAddr : FPAddr;
3326 }
else if (neededInt || neededSSE == 1) {
3328 auto TInfo = getContext().getTypeInfoInChars(Ty);
3329 uint64_t TySize = TInfo.Width.getQuantity();
3330 CharUnits TyAlign = TInfo.Align;
3331 llvm::Type *CoTy =
nullptr;
3335 llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset;
3336 uint64_t Alignment = neededInt ? 8 : 16;
3337 uint64_t RegSize = neededInt ? neededInt * 8 : 16;
3362 llvm::Value *PtrOffset =
3384 assert(neededSSE == 2 &&
"Invalid number of needed registers!");
3417 llvm::Value *Offset = llvm::ConstantInt::get(CGF.
Int32Ty, neededInt * 8);
3422 llvm::Value *Offset = llvm::ConstantInt::get(CGF.
Int32Ty, neededSSE * 16);
3441RValue X86_64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
3442 QualType Ty, AggValueSlot Slot)
const {
3445 uint64_t Width = getContext().getTypeSize(Ty);
3446 bool IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
3454ABIArgInfo WinX86_64ABIInfo::reclassifyHvaArgForVectorCall(
3455 QualType Ty,
unsigned &FreeSSERegs,
const ABIArgInfo ¤t)
const {
3460 isHomogeneousAggregate(Ty, Base, NumElts) && FreeSSERegs >= NumElts) {
3461 FreeSSERegs -= NumElts;
3462 return getDirectX86Hva();
3467ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty,
unsigned &FreeSSERegs,
3468 ClassifyKind Kind,
unsigned CC)
const {
3469 bool IsVectorCall = CC == llvm::CallingConv::X86_VectorCall;
3470 bool IsRegCall = CC == llvm::CallingConv::X86_RegCall;
3475 bool PromoteScopedEnum =
false;
3477 Ty = ED->getIntegerType();
3478 PromoteScopedEnum =
Kind == ClassifyKind::VarArg && ED->isScoped() &&
3479 getContext().isPromotableIntegerType(Ty);
3486 if (PromoteScopedEnum)
3489 TypeInfo Info = getContext().getTypeInfo(Ty);
3491 CharUnits Align = getContext().toCharUnitsFromBits(Info.
Align);
3495 if (Kind != ClassifyKind::Return) {
3497 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
3501 if (RT->getDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())
3502 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
3510 if ((IsVectorCall || IsRegCall) &&
3511 isHomogeneousAggregate(Ty, Base, NumElts)) {
3513 if (FreeSSERegs >= NumElts) {
3514 FreeSSERegs -= NumElts;
3521 Align, getDataLayout().getAllocaAddrSpace(),
3523 }
else if (IsVectorCall) {
3524 if (FreeSSERegs >= NumElts &&
3527 FreeSSERegs -= NumElts;
3529 }
else if (Kind == ClassifyKind::Return) {
3534 Align, getDataLayout().getAllocaAddrSpace(),
3543 llvm::Type *LLTy = CGT.ConvertType(Ty);
3544 if (LLTy->isPointerTy() || LLTy->isIntegerTy())
3551 if (Width > 64 || !llvm::isPowerOf2_64(Width))
3552 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
3559 if (
const BuiltinType *BT = Ty->
getAs<BuiltinType>()) {
3560 switch (BT->getKind()) {
3561 case BuiltinType::Bool:
3566 case BuiltinType::LongDouble:
3570 const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
3571 if (LDF == &llvm::APFloat::x87DoubleExtended())
3573 Align, getDataLayout().getAllocaAddrSpace(),
3578 case BuiltinType::Int128:
3579 case BuiltinType::UInt128:
3580 case BuiltinType::Float128:
3584 if (Kind != ClassifyKind::Return)
3586 Align, getDataLayout().getAllocaAddrSpace(),
3591 if (BT->getKind() == BuiltinType::Int128 ||
3592 BT->getKind() == BuiltinType::UInt128)
3594 llvm::Type::getInt64Ty(getVMContext()), 2));
3598 if (BT->getKind() == BuiltinType::Float128) {
3599 auto IsWin64F128StackCC = [
this](
unsigned CC) ->
bool {
3601 case llvm::CallingConv::Win64:
3603 case llvm::CallingConv::C:
3604 return getTarget().getTriple().isOSWindowsOrUEFI();
3610 if (IsWin64F128StackCC(CC))
3611 return getNaturalAlignIndirect(
3612 Ty, getDataLayout().getAllocaAddrSpace(),
false);
3630 Align, getDataLayout().getAllocaAddrSpace(),
3638WinX86_64ABIInfo::getX86ABIAVXLevel(
const FunctionDecl *FD,
3639 const FunctionType::ExtInfo &Info)
const {
3644 return static_cast<unsigned>(AVXLevel);
3647void WinX86_64ABIInfo::computeInfo(CGFunctionInfo &FI)
const {
3649 bool IsVectorCall = CC == llvm::CallingConv::X86_VectorCall;
3650 bool IsRegCall = CC == llvm::CallingConv::X86_RegCall;
3654 if (CC == llvm::CallingConv::X86_64_SysV) {
3655 X86_64ABIInfo SysVABIInfo(CGT, AVXLevel);
3656 SysVABIInfo.computeInfo(FI);
3660 unsigned FreeSSERegs = 0;
3664 }
else if (IsRegCall) {
3671 classify(FI.
getReturnType(), FreeSSERegs, ClassifyKind::Return, CC);
3676 }
else if (IsRegCall) {
3681 unsigned ArgNum = 0;
3682 unsigned ZeroSSERegs = 0;
3687 unsigned *MaybeFreeSSERegs =
3688 (IsVectorCall && ArgNum >= 6) ? &ZeroSSERegs : &FreeSSERegs;
3690 ? ClassifyKind::VarArg
3691 : ClassifyKind::FixedArgument;
3692 I.
info = classify(I.
type, *MaybeFreeSSERegs, Kind, CC);
3700 I.
info = reclassifyHvaArgForVectorCall(I.
type, FreeSSERegs, I.
info);
3704RValue WinX86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
3705 QualType Ty, AggValueSlot Slot)
const {
3708 uint64_t Width = getContext().getTypeSize(Ty);
3709 bool IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
3718 CodeGenModule &CGM,
bool DarwinVectorABI,
bool Win32StructABI,
3719 unsigned NumRegisterParameters,
bool SoftFloatABI) {
3720 bool RetSmallStructInRegABI = X86_32TargetCodeGenInfo::isStructReturnInRegABI(
3722 return std::make_unique<X86_32TargetCodeGenInfo>(
3723 CGM.
getTypes(), DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI,
3724 NumRegisterParameters, SoftFloatABI);
3728 CodeGenModule &CGM,
bool DarwinVectorABI,
bool Win32StructABI,
3729 unsigned NumRegisterParameters) {
3730 bool RetSmallStructInRegABI = X86_32TargetCodeGenInfo::isStructReturnInRegABI(
3732 return std::make_unique<WinX86_32TargetCodeGenInfo>(
3733 CGM.
getTypes(), DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI,
3734 NumRegisterParameters);
3737std::unique_ptr<TargetCodeGenInfo>
3740 return std::make_unique<X86_64TargetCodeGenInfo>(CGM.
getTypes(), AVXLevel);
3743std::unique_ptr<TargetCodeGenInfo>
3746 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 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.
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
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)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
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
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
@ Type
The name was classified as a type.
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