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)
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,
634X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty)
const {
639 if (
const BuiltinType *BT =
T->
getAs<BuiltinType>()) {
641 if (K == BuiltinType::Float || K == BuiltinType::Double)
647bool X86_32ABIInfo::updateFreeRegs(QualType Ty, CCState &State)
const {
648 if (!IsSoftFloatABI) {
654 unsigned Size = getContext().getTypeSize(Ty);
655 unsigned SizeInRegs = (
Size + 31) / 32;
661 if (SizeInRegs > State.FreeRegs) {
670 if (SizeInRegs > State.FreeRegs || SizeInRegs > 2)
674 State.FreeRegs -= SizeInRegs;
678bool X86_32ABIInfo::shouldAggregateUseDirect(QualType Ty, CCState &State,
680 bool &NeedsPadding)
const {
687 NeedsPadding =
false;
690 if (!updateFreeRegs(Ty, State))
696 if (State.CC == llvm::CallingConv::X86_FastCall ||
697 State.CC == llvm::CallingConv::X86_VectorCall ||
698 State.CC == llvm::CallingConv::X86_RegCall) {
699 if (getContext().getTypeSize(Ty) <= 32 && State.FreeRegs)
708bool X86_32ABIInfo::shouldPrimitiveUseInReg(QualType Ty, CCState &State)
const {
709 bool IsPtrOrInt = (getContext().getTypeSize(Ty) <= 32) &&
713 if (!IsPtrOrInt && (State.CC == llvm::CallingConv::X86_FastCall ||
714 State.CC == llvm::CallingConv::X86_VectorCall))
717 if (!updateFreeRegs(Ty, State))
720 if (!IsPtrOrInt && State.CC == llvm::CallingConv::X86_RegCall)
727void X86_32ABIInfo::runVectorCallFirstPass(CGFunctionInfo &FI, CCState &State)
const {
737 MutableArrayRef<CGFunctionInfoArgInfo> Args = FI.
arguments();
738 for (
int I = 0, E = Args.size(); I < E; ++I) {
741 const QualType &Ty = Args[I].type;
743 isHomogeneousAggregate(Ty, Base, NumElts)) {
744 if (State.FreeSSERegs >= NumElts) {
745 State.FreeSSERegs -= NumElts;
747 State.IsPreassigned.set(I);
753ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State,
754 unsigned ArgIndex)
const {
756 bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall;
757 bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall;
758 bool IsVectorCall = State.CC == llvm::CallingConv::X86_VectorCall;
761 TypeInfo TI = getContext().getTypeInfo(Ty);
768 return getIndirectResult(Ty,
false, State);
769 }
else if (State.IsDelegateCall) {
772 ABIArgInfo Res = getIndirectResult(Ty,
false, State);
785 if ((IsRegCall || IsVectorCall) &&
786 isHomogeneousAggregate(Ty, Base, NumElts)) {
787 if (State.FreeSSERegs >= NumElts) {
788 State.FreeSSERegs -= NumElts;
793 return getDirectX86Hva();
801 return getIndirectResult(Ty,
false, State);
807 if (RT && RT->getDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())
808 return getIndirectResult(Ty,
true, State);
811 if (!IsWin32StructABI &&
isEmptyRecord(getContext(), Ty,
true))
818 llvm::LLVMContext &LLVMContext = getVMContext();
819 llvm::IntegerType *
Int32 = llvm::Type::getInt32Ty(LLVMContext);
820 bool NeedsPadding =
false;
822 if (shouldAggregateUseDirect(Ty, State, InReg, NeedsPadding)) {
823 unsigned SizeInRegs = (TI.
Width + 31) / 32;
824 SmallVector<llvm::Type*, 3> Elements(SizeInRegs, Int32);
825 llvm::Type *
Result = llvm::StructType::get(LLVMContext, Elements);
831 llvm::IntegerType *PaddingType = NeedsPadding ?
Int32 :
nullptr;
838 if (IsWin32StructABI && State.Required.
isRequiredArg(ArgIndex)) {
839 unsigned AlignInBits = 0;
841 const ASTRecordLayout &Layout =
842 getContext().getASTRecordLayout(RT->getDecl());
845 AlignInBits = TI.
Align;
847 if (AlignInBits > 32)
848 return getIndirectResult(Ty,
false, State);
857 if (TI.
Width <= 4 * 32 && (!IsMCUABI || State.FreeRegs == 0) &&
858 canExpandIndirectArgument(Ty))
860 IsFastCall || IsVectorCall || IsRegCall, PaddingType);
862 return getIndirectResult(Ty,
true, State);
865 if (
const VectorType *VT = Ty->
getAs<VectorType>()) {
869 if (IsWin32StructABI) {
870 if (TI.
Width <= 512 && State.FreeSSERegs > 0) {
874 return getIndirectResult(Ty,
false, State);
879 if (IsDarwinVectorABI) {
881 (TI.
Width == 64 && VT->getNumElements() == 1))
883 llvm::IntegerType::get(getVMContext(), TI.
Width));
886 if (IsX86_MMXType(CGT.ConvertType(Ty)))
893 Ty = ED->getIntegerType();
895 bool InReg = shouldPrimitiveUseInReg(Ty, State);
897 if (isPromotableIntegerTypeForABI(Ty)) {
903 if (
const auto *EIT = Ty->
getAs<BitIntType>()) {
904 if (EIT->getNumBits() <= 64) {
909 return getIndirectResult(Ty,
false, State);
917void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI)
const {
921 else if (State.CC == llvm::CallingConv::X86_FastCall) {
923 State.FreeSSERegs = 3;
924 }
else if (State.CC == llvm::CallingConv::X86_VectorCall) {
926 State.FreeSSERegs = 6;
929 else if (State.CC == llvm::CallingConv::X86_RegCall) {
931 State.FreeSSERegs = 8;
932 }
else if (IsWin32StructABI) {
935 State.FreeRegs = DefaultNumRegisterParameters;
936 State.FreeSSERegs = 3;
938 State.FreeRegs = DefaultNumRegisterParameters;
945 if (State.FreeRegs) {
958 if (State.CC == llvm::CallingConv::X86_VectorCall)
959 runVectorCallFirstPass(FI, State);
961 bool UsedInAlloca =
false;
962 MutableArrayRef<CGFunctionInfoArgInfo> Args = FI.
arguments();
963 for (
unsigned I = 0, E = Args.size(); I < E; ++I) {
965 if (State.IsPreassigned.test(I))
976 rewriteWithInAlloca(FI);
980X86_32ABIInfo::addFieldToArgStruct(SmallVector<llvm::Type *, 6> &FrameFields,
981 CharUnits &StackOffset, ABIArgInfo &Info,
982 QualType
Type)
const {
985 assert(StackOffset.
isMultipleOf(WordSize) &&
"unaligned inalloca struct");
990 bool IsIndirect =
false;
994 llvm::Type *LLTy = CGT.ConvertTypeForMem(
Type);
996 LLTy = llvm::PointerType::getUnqual(getVMContext());
997 FrameFields.push_back(LLTy);
998 StackOffset += IsIndirect ? WordSize : getContext().getTypeSizeInChars(
Type);
1001 CharUnits FieldEnd = StackOffset;
1002 StackOffset = FieldEnd.
alignTo(WordSize);
1003 if (StackOffset != FieldEnd) {
1004 CharUnits NumBytes = StackOffset - FieldEnd;
1005 llvm::Type *Ty = llvm::Type::getInt8Ty(getVMContext());
1006 Ty = llvm::ArrayType::get(Ty, NumBytes.
getQuantity());
1007 FrameFields.push_back(Ty);
1030 llvm_unreachable(
"invalid enum");
1033void X86_32ABIInfo::rewriteWithInAlloca(CGFunctionInfo &FI)
const {
1034 assert(IsWin32StructABI &&
"inalloca only supported on win32");
1037 SmallVector<llvm::Type *, 6> FrameFields;
1042 CharUnits StackOffset;
1049 if (
Ret.isIndirect() &&
Ret.isSRetAfterThis() && !IsThisCall &&
1051 addFieldToArgStruct(FrameFields, StackOffset, I->
info, I->
type);
1056 if (
Ret.isIndirect() && !
Ret.getInReg()) {
1057 addFieldToArgStruct(FrameFields, StackOffset, Ret, FI.
getReturnType());
1059 Ret.setInAllocaSRet(IsWin32StructABI);
1067 for (; I != E; ++I) {
1069 addFieldToArgStruct(FrameFields, StackOffset, I->
info, I->
type);
1072 FI.
setArgStruct(llvm::StructType::get(getVMContext(), FrameFields,
1077RValue X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
1078 QualType Ty, AggValueSlot Slot)
const {
1080 auto TypeInfo = getContext().getTypeInfoInChars(Ty);
1082 CCState State(*
const_cast<CGFunctionInfo *
>(CGF.
CurFnInfo));
1093 getTypeStackAlignInBytes(Ty, TypeInfo.Align.getQuantity()));
1100bool X86_32TargetCodeGenInfo::isStructReturnInRegABI(
1101 const llvm::Triple &Triple,
const CodeGenOptions &Opts) {
1102 assert(Triple.getArch() == llvm::Triple::x86);
1104 switch (Opts.getStructReturnConvention()) {
1113 if (Triple.isOSDarwin() || Triple.isOSIAMCU())
1116 switch (Triple.getOS()) {
1117 case llvm::Triple::DragonFly:
1118 case llvm::Triple::FreeBSD:
1119 case llvm::Triple::OpenBSD:
1120 case llvm::Triple::Win32:
1129 if (!FD->
hasAttr<AnyX86InterruptAttr>())
1133 Fn->setCallingConv(llvm::CallingConv::X86_INTR);
1139 llvm::Attribute NewAttr = llvm::Attribute::getWithByValType(
1140 Fn->getContext(), ByValTy);
1141 Fn->addParamAttr(0, NewAttr);
1144void X86_32TargetCodeGenInfo::setTargetAttributes(
1145 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM)
const {
1146 if (GV->isDeclaration())
1148 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
1149 if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
1151 Fn->addFnAttr(
"stackrealign");
1158bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable(
1159 CodeGen::CodeGenFunction &CGF,
1160 llvm::Value *Address)
const {
1161 CodeGen::CGBuilderTy &Builder = CGF.
Builder;
1163 llvm::Value *Four8 = llvm::ConstantInt::get(CGF.
Int8Ty, 4);
1174 llvm::Value *Sixteen8 = llvm::ConstantInt::get(CGF.
Int8Ty, 16);
1180 Builder.CreateAlignedStore(
1181 Four8, Builder.CreateConstInBoundsGEP1_32(CGF.
Int8Ty, Address, 9),
1187 llvm::Value *Twelve8 = llvm::ConstantInt::get(CGF.
Int8Ty, 12);
1202static unsigned getNativeVectorSizeForAVXABI(
X86AVXABILevel AVXLevel) {
1204 case X86AVXABILevel::AVX512:
1206 case X86AVXABILevel::AVX:
1208 case X86AVXABILevel::None:
1211 llvm_unreachable(
"Unknown AVXLevel");
1215class X86_64ABIInfo :
public ABIInfo {
1252 void postMerge(
unsigned AggregateSize,
Class &Lo,
Class &Hi)
const;
1280 void classify(QualType
T, uint64_t OffsetBase,
Class &Lo,
Class &Hi,
1281 bool isNamedArg,
bool IsRegCall =
false)
const;
1283 llvm::Type *GetByteVectorType(QualType Ty)
const;
1284 llvm::Type *GetSSETypeAtOffset(llvm::Type *IRType,
1285 unsigned IROffset, QualType SourceTy,
1286 unsigned SourceOffset)
const;
1287 llvm::Type *GetINTEGERTypeAtOffset(llvm::Type *IRType,
1288 unsigned IROffset, QualType SourceTy,
1289 unsigned SourceOffset)
const;
1293 ABIArgInfo getIndirectReturnResult(QualType Ty)
const;
1300 ABIArgInfo getIndirectResult(QualType Ty,
unsigned freeIntRegs)
const;
1305 unsigned &neededInt,
unsigned &neededSSE,
1307 bool IsRegCall =
false)
const;
1309 ABIArgInfo classifyRegCallStructType(QualType Ty,
unsigned &NeededInt,
1310 unsigned &NeededSSE,
1311 unsigned &MaxVectorWidth)
const;
1313 bool passRegCallStructTypeDirectly(QualType Ty,
1314 SmallVectorImpl<llvm::Type *> &CoerceElts,
1315 unsigned &NeededInt,
unsigned &NeededSSE,
1316 unsigned &MaxVectorWidth)
const;
1318 bool IsIllegalVectorType(QualType Ty)
const;
1325 bool honorsRevision0_98()
const {
1326 return !getTarget().getTriple().isOSDarwin();
1331 bool classifyIntegerMMXAsSSE()
const {
1333 if (getContext().getLangOpts().isCompatibleWith(
1334 LangOptions::ClangABI::Ver3_8))
1337 const llvm::Triple &Triple = getTarget().getTriple();
1338 if (Triple.isOSDarwin() || Triple.isPS() || Triple.isOSFreeBSD())
1344 bool passInt128VectorsInMem()
const {
1346 if (getContext().getLangOpts().isCompatibleWith(
1347 LangOptions::ClangABI::Ver9))
1350 const llvm::Triple &
T = getTarget().getTriple();
1351 return T.isOSLinux() ||
T.isOSNetBSD();
1354 bool returnCXXRecordGreaterThan128InMem()
const {
1356 if (getContext().getLangOpts().isCompatibleWith(
1357 LangOptions::ClangABI::Ver20) ||
1367 bool Has64BitPointers;
1370 X86_64ABIInfo(CodeGen::CodeGenTypes &CGT,
X86AVXABILevel AVXLevel)
1371 : ABIInfo(CGT), AVXLevel(AVXLevel),
1372 Has64BitPointers(CGT.getDataLayout().getPointerSize(0) == 8) {}
1374 bool isPassedUsingAVXType(QualType
type)
const {
1375 unsigned neededInt, neededSSE;
1381 if (llvm::VectorType *vectorTy = dyn_cast_or_null<llvm::VectorType>(ty))
1382 return vectorTy->getPrimitiveSizeInBits().getFixedValue() > 128;
1387 void computeInfo(CGFunctionInfo &FI)
const override;
1388 unsigned getX86ABIAVXLevel(
const FunctionDecl *FD,
1389 const FunctionType::ExtInfo &Info)
const override;
1391 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
1392 AggValueSlot Slot)
const override;
1393 RValue EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
1394 AggValueSlot Slot)
const override;
1396 bool has64BitPointers()
const {
1397 return Has64BitPointers;
1402class WinX86_64ABIInfo :
public ABIInfo {
1404 WinX86_64ABIInfo(CodeGen::CodeGenTypes &CGT,
X86AVXABILevel AVXLevel)
1405 : ABIInfo(CGT), AVXLevel(AVXLevel),
1406 IsMingw64(getTarget().
getTriple().isWindowsGNUEnvironment()) {}
1408 void computeInfo(CGFunctionInfo &FI)
const override;
1409 unsigned getX86ABIAVXLevel(
const FunctionDecl *FD,
1410 const FunctionType::ExtInfo &Info)
const override;
1412 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
1413 AggValueSlot Slot)
const override;
1415 bool isHomogeneousAggregateBaseType(QualType Ty)
const override {
1417 return isX86VectorTypeForVectorCall(getContext(), Ty);
1420 bool isHomogeneousAggregateSmallEnough(
const Type *Ty,
1421 uint64_t NumMembers)
const override {
1423 return isX86VectorCallAggregateSmallEnough(NumMembers);
1426 ABIArgInfo classifyArgForArm64ECVarArg(QualType Ty)
const override {
1427 unsigned FreeSSERegs = 0;
1428 return classify(Ty, FreeSSERegs,
false,
1429 llvm::CallingConv::C);
1433 ABIArgInfo classify(QualType Ty,
unsigned &FreeSSERegs,
bool IsReturnType,
1435 ABIArgInfo reclassifyHvaArgForVectorCall(QualType Ty,
unsigned &FreeSSERegs,
1436 const ABIArgInfo ¤t)
const;
1443class X86_64TargetCodeGenInfo :
public TargetCodeGenInfo {
1445 X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
X86AVXABILevel AVXLevel)
1446 : TargetCodeGenInfo(std::make_unique<X86_64ABIInfo>(CGT, AVXLevel)) {
1448 std::make_unique<SwiftABIInfo>(CGT,
true);
1453 bool markARCOptimizedReturnCallsAsNoTail()
const override {
return true; }
1455 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM)
const override {
1459 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
1460 llvm::Value *Address)
const override {
1461 llvm::Value *Eight8 = llvm::ConstantInt::get(CGF.
Int8Ty, 8);
1469 llvm::Type* adjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
1470 StringRef Constraint,
1471 llvm::Type* Ty)
const override {
1472 return X86AdjustInlineAsmType(CGF, Constraint, Ty);
1475 bool isNoProtoCallVariadic(
const CallArgList &args,
1476 const FunctionNoProtoType *fnType)
const override {
1484 bool HasAVXType =
false;
1485 for (
const CallArg &arg : args) {
1486 if (getABIInfo<X86_64ABIInfo>().isPassedUsingAVXType(
arg.Ty)) {
1499 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1500 CodeGen::CodeGenModule &CGM)
const override {
1501 if (GV->isDeclaration())
1503 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
1504 if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
1506 Fn->addFnAttr(
"stackrealign");
1513 void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc,
1514 const FunctionDecl *Caller,
1515 const FunctionDecl *Callee,
const CallArgList &Args,
1516 QualType ReturnType)
const override;
1518 void checkFunctionABI(CodeGenModule &CGM,
1519 const FunctionDecl *FD)
const override;
1524 llvm::StringMap<bool> &CallerMap,
1526 llvm::StringMap<bool> &CalleeMap,
1528 if (CalleeMap.empty() && CallerMap.empty()) {
1540 const llvm::StringMap<bool> &CallerMap,
1541 const llvm::StringMap<bool> &CalleeMap,
1544 bool CallerHasFeat = CallerMap.lookup(
Feature);
1545 bool CalleeHasFeat = CalleeMap.lookup(
Feature);
1547 if (!CallerHasFeat && !CalleeHasFeat &&
1548 (!Callee.isExternallyVisible() || Callee.hasAttr<AlwaysInlineAttr>()))
1551 if (!CallerHasFeat && !CalleeHasFeat)
1552 return Diag.Report(CallLoc, diag::warn_avx_calling_convention)
1553 << IsArgument << Ty <<
Feature;
1556 if (!CallerHasFeat || !CalleeHasFeat)
1557 return Diag.Report(CallLoc, diag::err_avx_calling_convention)
1558 << IsArgument << Ty <<
Feature;
1567 const llvm::StringMap<bool> &CallerMap,
1568 const llvm::StringMap<bool> &CalleeMap,
QualType Ty,
1573 "avx512f", IsArgument);
1582void X86_64TargetCodeGenInfo::checkFunctionABI(CodeGenModule &CGM,
1583 const FunctionDecl *FD)
const {
1584 auto GetReturnTypeLoc = [](
const FunctionDecl *FD) {
1586 TypeLoc TL = TSI->getTypeLoc();
1589 SourceLocation Loc = FTL.getReturnLoc().getBeginLoc();
1602 auto Check = [&](QualType Ty, SourceLocation Loc,
bool IsReturn) {
1611 llvm::StringMap<bool> FeatureMap;
1613 if (!FeatureMap.lookup(
Feature)) {
1615 << !IsReturn << Ty <<
Feature;
1632 for (
const ParmVarDecl *P : FD->
parameters()) {
1633 SourceLocation Loc = P->getLocation();
1635 Loc = P->getBeginLoc();
1636 if (Check(P->getType(), Loc,
false))
1641void X86_64TargetCodeGenInfo::checkFunctionCallABI(CodeGenModule &CGM,
1642 SourceLocation CallLoc,
1643 const FunctionDecl *Caller,
1644 const FunctionDecl *Callee,
1645 const CallArgList &Args,
1646 QualType ReturnType)
const {
1650 llvm::StringMap<bool> CallerMap;
1651 llvm::StringMap<bool> CalleeMap;
1652 unsigned ArgIndex = 0;
1656 for (
const CallArg &Arg : Args) {
1664 if (Arg.getType()->isVectorType() &&
1667 QualType Ty = Arg.getType();
1670 if (ArgIndex < Callee->getNumParams())
1671 Ty =
Callee->getParamDecl(ArgIndex)->getType();
1674 CallerMap, CalleeMap, Ty,
true))
1682 if (
Callee->getReturnType()->isVectorType() &&
1686 CalleeMap,
Callee->getReturnType(),
1695 bool Quote = Lib.contains(
' ');
1696 std::string ArgStr = Quote ?
"\"" :
"";
1698 if (!Lib.ends_with_insensitive(
".lib") && !Lib.ends_with_insensitive(
".a"))
1700 ArgStr += Quote ?
"\"" :
"";
1705class WinX86_32TargetCodeGenInfo :
public X86_32TargetCodeGenInfo {
1708 bool DarwinVectorABI,
bool RetSmallStructInRegABI,
bool Win32StructABI,
1709 unsigned NumRegisterParameters)
1710 : X86_32TargetCodeGenInfo(CGT, DarwinVectorABI, RetSmallStructInRegABI,
1711 Win32StructABI, NumRegisterParameters,
false) {}
1713 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1716 void getDependentLibraryOption(llvm::StringRef Lib,
1718 Opt =
"/DEFAULTLIB:";
1719 Opt += qualifyWindowsLibrary(Lib);
1722 void getDetectMismatchOption(llvm::StringRef Name,
1723 llvm::StringRef
Value,
1725 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
1730void WinX86_32TargetCodeGenInfo::setTargetAttributes(
1731 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM)
const {
1732 X86_32TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
1733 if (GV->isDeclaration())
1735 addStackProbeTargetAttributes(D, GV, CGM);
1739class WinX86_64TargetCodeGenInfo :
public TargetCodeGenInfo {
1741 WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
1743 : TargetCodeGenInfo(std::make_unique<WinX86_64ABIInfo>(CGT, AVXLevel)) {
1745 std::make_unique<SwiftABIInfo>(CGT,
true);
1748 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1749 CodeGen::CodeGenModule &CGM)
const override;
1751 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM)
const override {
1755 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
1756 llvm::Value *Address)
const override {
1757 llvm::Value *Eight8 = llvm::ConstantInt::get(CGF.
Int8Ty, 8);
1765 void getDependentLibraryOption(llvm::StringRef Lib,
1766 llvm::SmallString<24> &Opt)
const override {
1767 Opt =
"/DEFAULTLIB:";
1768 Opt += qualifyWindowsLibrary(Lib);
1771 void getDetectMismatchOption(llvm::StringRef Name,
1772 llvm::StringRef
Value,
1773 llvm::SmallString<32> &Opt)
const override {
1774 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
1779void WinX86_64TargetCodeGenInfo::setTargetAttributes(
1780 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM)
const {
1782 if (GV->isDeclaration())
1784 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
1785 if (FD->
hasAttr<X86ForceAlignArgPointerAttr>()) {
1787 Fn->addFnAttr(
"stackrealign");
1793 addStackProbeTargetAttributes(D, GV, CGM);
1796void X86_64ABIInfo::postMerge(
unsigned AggregateSize,
Class &Lo,
1821 if (Hi == X87Up && Lo != X87 && honorsRevision0_98())
1823 if (AggregateSize > 128 && (Lo != SSE || Hi != SSEUp))
1825 if (Hi == SSEUp && Lo != SSE)
1835 LangOptions::ClangABI::Ver23) {
1836 return GlobalAVXLevel;
1843 if (!FD || !FD->
hasAttr<TargetAttr>())
1846 llvm::StringMap<bool> FeatureMap;
1848 if (FeatureMap.lookup(
"avx512f"))
1850 if (FeatureMap.lookup(
"avx"))
1855X86_64ABIInfo::Class X86_64ABIInfo::merge(
Class Accum,
Class Field) {
1879 assert((Accum != Memory && Accum != ComplexX87) &&
1880 "Invalid accumulated classification during merge.");
1881 if (Accum == Field || Field == NoClass)
1883 if (Field == Memory)
1885 if (Accum == NoClass)
1889 if (Field == X87 || Field == X87Up || Field == ComplexX87 ||
1890 Accum == X87 || Accum == X87Up)
1895void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
Class &Lo,
1896 Class &Hi,
bool isNamedArg,
bool IsRegCall)
const {
1907 Class &Current = OffsetBase < 64 ? Lo : Hi;
1910 if (
const BuiltinType *BT = Ty->
getAs<BuiltinType>()) {
1913 if (k == BuiltinType::Void) {
1915 }
else if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
1918 }
else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
1920 }
else if (k == BuiltinType::Float || k == BuiltinType::Double ||
1921 k == BuiltinType::Float16 || k == BuiltinType::BFloat16) {
1923 }
else if (k == BuiltinType::Float128) {
1926 }
else if (k == BuiltinType::LongDouble) {
1927 const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
1928 if (LDF == &llvm::APFloat::IEEEquad()) {
1931 }
else if (LDF == &llvm::APFloat::x87DoubleExtended()) {
1934 }
else if (LDF == &llvm::APFloat::IEEEdouble()) {
1937 llvm_unreachable(
"unexpected long double representation!");
1946 classify(ED->getIntegerType(), OffsetBase, Lo, Hi, isNamedArg);
1957 if (Has64BitPointers) {
1964 uint64_t EB_FuncPtr = (OffsetBase) / 64;
1965 uint64_t EB_ThisAdj = (OffsetBase + 64 - 1) / 64;
1966 if (EB_FuncPtr != EB_ThisAdj) {
1978 if (
const VectorType *VT = Ty->
getAs<VectorType>()) {
1980 if (Size == 1 || Size == 8 || Size == 16 || Size == 32) {
1989 uint64_t EB_Lo = (OffsetBase) / 64;
1993 }
else if (Size == 64) {
1994 QualType ElementType = VT->getElementType();
2003 if (!classifyIntegerMMXAsSSE() &&
2014 if (OffsetBase && OffsetBase != 64)
2016 }
else if (Size == 128 ||
2017 (isNamedArg && Size <= getNativeVectorSizeForAVXABI(AVXLevel))) {
2018 QualType ElementType = VT->getElementType();
2021 if (passInt128VectorsInMem() && Size != 128 &&
2046 if (
const ComplexType *CT = Ty->
getAs<ComplexType>()) {
2053 else if (Size <= 128)
2055 }
else if (ET->
isFloat16Type() || ET == getContext().FloatTy ||
2058 }
else if (ET == getContext().DoubleTy) {
2060 }
else if (ET == getContext().LongDoubleTy) {
2061 const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
2062 if (LDF == &llvm::APFloat::IEEEquad())
2064 else if (LDF == &llvm::APFloat::x87DoubleExtended())
2065 Current = ComplexX87;
2066 else if (LDF == &llvm::APFloat::IEEEdouble())
2069 llvm_unreachable(
"unexpected long double representation!");
2074 uint64_t EB_Real = (OffsetBase) / 64;
2075 uint64_t EB_Imag = (OffsetBase + getContext().getTypeSize(ET)) / 64;
2076 if (Hi == NoClass && EB_Real != EB_Imag)
2082 if (
const auto *EITy = Ty->
getAs<BitIntType>()) {
2083 if (EITy->getNumBits() <= 64)
2085 else if (EITy->getNumBits() <= 128)
2091 if (
const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
2100 if (!IsRegCall && Size > 512)
2107 if (OffsetBase % getContext().getTypeAlign(AT->getElementType()))
2113 uint64_t EltSize = getContext().getTypeSize(AT->getElementType());
2114 uint64_t ArraySize = AT->getZExtSize();
2121 (Size != EltSize || Size > getNativeVectorSizeForAVXABI(AVXLevel)))
2124 for (uint64_t i=0, Offset=OffsetBase; i<ArraySize; ++i, Offset += EltSize) {
2125 Class FieldLo, FieldHi;
2126 classify(AT->getElementType(), Offset, FieldLo, FieldHi, isNamedArg);
2127 Lo =
merge(Lo, FieldLo);
2128 Hi =
merge(Hi, FieldHi);
2129 if (Lo == Memory || Hi == Memory)
2133 postMerge(Size, Lo, Hi);
2134 assert((Hi != SSEUp || Lo == SSE) &&
"Invalid SSEUp array classification.");
2158 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
2164 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2165 for (
const auto &I : CXXRD->bases()) {
2166 assert(!I.isVirtual() && !I.getType()->isDependentType() &&
2167 "Unexpected base class!");
2168 const auto *
Base = I.getType()->castAsCXXRecordDecl();
2174 Class FieldLo, FieldHi;
2177 classify(I.getType(), Offset, FieldLo, FieldHi, isNamedArg);
2178 Lo =
merge(Lo, FieldLo);
2179 Hi =
merge(Hi, FieldHi);
2180 if (returnCXXRecordGreaterThan128InMem() &&
2182 (Size > 128 && (Size != getContext().getTypeSize(I.getType()) ||
2183 Size > getNativeVectorSizeForAVXABI(AVXLevel)))) {
2188 if (Lo == Memory || Hi == Memory) {
2189 postMerge(Size, Lo, Hi);
2197 bool UseClang11Compat = getContext().getLangOpts().isCompatibleWith(
2198 LangOptions::ClangABI::Ver11) ||
2199 getContext().getTargetInfo().getTriple().isPS();
2200 bool IsUnion = RT->isUnionType() && !UseClang11Compat;
2203 i != e; ++i, ++idx) {
2205 bool BitField = i->isBitField();
2208 if (BitField && i->isUnnamedBitField())
2221 ((!IsUnion && Size != getContext().getTypeSize(i->getType())) ||
2222 Size > getNativeVectorSizeForAVXABI(AVXLevel))) {
2224 postMerge(Size, Lo, Hi);
2229 Offset % getContext().getTypeAlign(i->getType().getCanonicalType());
2231 if (!BitField && IsInMemory) {
2233 postMerge(Size, Lo, Hi);
2243 Class FieldLo, FieldHi;
2249 assert(!i->isUnnamedBitField());
2257 assert(EB_Hi == EB_Lo &&
"Invalid classification, type > 16 bytes.");
2262 FieldHi = EB_Hi ?
Integer : NoClass;
2265 classify(i->getType(), Offset, FieldLo, FieldHi, isNamedArg);
2266 Lo =
merge(Lo, FieldLo);
2267 Hi =
merge(Hi, FieldHi);
2268 if (Lo == Memory || Hi == Memory)
2272 postMerge(Size, Lo, Hi);
2276ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty)
const {
2282 Ty = ED->getIntegerType();
2285 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
2287 llvm::Type *IRTy = CGT.ConvertType(Ty);
2292 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
2295bool X86_64ABIInfo::IsIllegalVectorType(QualType Ty)
const {
2296 if (
const VectorType *VecTy = Ty->
getAs<VectorType>()) {
2298 unsigned LargestVector = getNativeVectorSizeForAVXABI(AVXLevel);
2299 if (Size <= 64 || Size > LargestVector)
2301 QualType EltTy = VecTy->getElementType();
2302 if (passInt128VectorsInMem() &&
2311ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty,
2312 unsigned freeIntRegs)
const {
2325 Ty = ED->getIntegerType();
2327 llvm::Type *IRTy = CGT.ConvertType(Ty);
2333 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
2338 unsigned Align = std::max(getContext().getTypeAlign(Ty) / 8, 8U);
2361 if (freeIntRegs == 0) {
2366 if (Align == 8 && Size <= 64)
2372 getDataLayout().getAllocaAddrSpace());
2377llvm::Type *X86_64ABIInfo::GetByteVectorType(QualType Ty)
const {
2381 Ty = QualType(InnerTy, 0);
2383 llvm::Type *IRType = CGT.ConvertType(Ty);
2387 if (passInt128VectorsInMem() &&
2391 return llvm::FixedVectorType::get(llvm::Type::getInt64Ty(getVMContext()),
2398 if (IRType->getTypeID() == llvm::Type::FP128TyID)
2403 assert((Size == 128 || Size == 256 || Size == 512) &&
"Invalid type found!");
2407 return llvm::FixedVectorType::get(llvm::Type::getDoubleTy(getVMContext()),
2423 unsigned TySize = (
unsigned)Context.getTypeSize(Ty);
2424 if (TySize <= StartBit)
2428 unsigned EltSize = (
unsigned)Context.getTypeSize(AT->getElementType());
2429 unsigned NumElts = (
unsigned)AT->getZExtSize();
2432 for (
unsigned i = 0; i != NumElts; ++i) {
2434 unsigned EltOffset = i*EltSize;
2435 if (EltOffset >= EndBit)
break;
2437 unsigned EltStart = EltOffset < StartBit ? StartBit-EltOffset :0;
2439 EndBit-EltOffset, Context))
2450 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2451 for (
const auto &I : CXXRD->bases()) {
2452 assert(!I.isVirtual() && !I.getType()->isDependentType() &&
2453 "Unexpected base class!");
2454 const auto *
Base = I.getType()->castAsCXXRecordDecl();
2458 if (BaseOffset >= EndBit)
continue;
2460 unsigned BaseStart = BaseOffset < StartBit ? StartBit-BaseOffset :0;
2462 EndBit-BaseOffset, Context))
2473 i != e; ++i, ++idx) {
2477 if (FieldOffset >= EndBit)
break;
2479 unsigned FieldStart = FieldOffset < StartBit ? StartBit-FieldOffset :0;
2495 const llvm::DataLayout &TD) {
2496 if (IROffset == 0 && IRType->isFloatingPointTy())
2500 if (llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) {
2501 if (!STy->getNumContainedTypes())
2504 const llvm::StructLayout *SL = TD.getStructLayout(STy);
2505 unsigned Elt = SL->getElementContainingOffset(IROffset);
2506 IROffset -= SL->getElementOffset(Elt);
2511 if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) {
2512 llvm::Type *EltTy = ATy->getElementType();
2513 unsigned EltSize = TD.getTypeAllocSize(EltTy);
2514 IROffset -= IROffset / EltSize * EltSize;
2523llvm::Type *X86_64ABIInfo::
2524GetSSETypeAtOffset(llvm::Type *IRType,
unsigned IROffset,
2525 QualType SourceTy,
unsigned SourceOffset)
const {
2526 const llvm::DataLayout &TD = getDataLayout();
2527 unsigned SourceSize =
2528 (unsigned)getContext().getTypeSize(SourceTy) / 8 - SourceOffset;
2530 if (!T0 || T0->isDoubleTy())
2531 return llvm::Type::getDoubleTy(getVMContext());
2534 llvm::Type *T1 =
nullptr;
2535 unsigned T0Size = TD.getTypeAllocSize(T0);
2536 if (SourceSize > T0Size)
2538 if (T1 ==
nullptr) {
2541 if (T0->is16bitFPTy() && SourceSize > 4)
2550 if (T0->isFloatTy() && T1->isFloatTy())
2551 return llvm::FixedVectorType::get(T0, 2);
2553 if (T0->is16bitFPTy() && T1->is16bitFPTy()) {
2554 llvm::Type *T2 =
nullptr;
2558 return llvm::FixedVectorType::get(T0, 2);
2559 return llvm::FixedVectorType::get(T0, 4);
2562 if (T0->is16bitFPTy() || T1->is16bitFPTy())
2563 return llvm::FixedVectorType::get(llvm::Type::getHalfTy(getVMContext()), 4);
2565 return llvm::Type::getDoubleTy(getVMContext());
2582llvm::Type *X86_64ABIInfo::
2583GetINTEGERTypeAtOffset(llvm::Type *IRType,
unsigned IROffset,
2584 QualType SourceTy,
unsigned SourceOffset)
const {
2587 if (IROffset == 0) {
2590 IRType->isIntegerTy(64))
2599 if (IRType->isIntegerTy(8) || IRType->isIntegerTy(16) ||
2600 IRType->isIntegerTy(32) ||
2606 SourceOffset*8+64, getContext()))
2611 if (llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) {
2613 const llvm::StructLayout *SL = getDataLayout().getStructLayout(STy);
2614 if (IROffset < SL->getSizeInBytes()) {
2615 unsigned FieldIdx = SL->getElementContainingOffset(IROffset);
2616 IROffset -= SL->getElementOffset(FieldIdx);
2618 return GetINTEGERTypeAtOffset(STy->getElementType(FieldIdx), IROffset,
2619 SourceTy, SourceOffset);
2623 if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) {
2624 llvm::Type *EltTy = ATy->getElementType();
2625 unsigned EltSize = getDataLayout().getTypeAllocSize(EltTy);
2626 unsigned EltOffset = IROffset/EltSize*EltSize;
2627 return GetINTEGERTypeAtOffset(EltTy, IROffset-EltOffset, SourceTy,
2633 if (IRType->isIntegerTy(128)) {
2634 assert(IROffset == 0);
2640 unsigned TySizeInBytes =
2641 (unsigned)getContext().getTypeSizeInChars(SourceTy).getQuantity();
2643 assert(TySizeInBytes != SourceOffset &&
"Empty field?");
2647 return llvm::IntegerType::get(getVMContext(),
2648 std::min(TySizeInBytes-SourceOffset, 8U)*8);
2659 const llvm::DataLayout &TD) {
2664 unsigned LoSize = (
unsigned)TD.getTypeAllocSize(Lo);
2665 llvm::Align HiAlign = TD.getABITypeAlign(Hi);
2666 unsigned HiStart = llvm::alignTo(LoSize, HiAlign);
2667 assert(HiStart != 0 && HiStart <= 8 &&
"Invalid x86-64 argument pair!");
2678 if (Lo->isHalfTy() || Lo->isFloatTy())
2679 Lo = llvm::Type::getDoubleTy(Lo->getContext());
2681 assert((Lo->isIntegerTy() || Lo->isPointerTy())
2682 &&
"Invalid/unknown lo type");
2683 Lo = llvm::Type::getInt64Ty(Lo->getContext());
2687 llvm::StructType *
Result = llvm::StructType::get(Lo, Hi);
2690 assert(TD.getStructLayout(
Result)->getElementOffset(1) == 8 &&
2691 "Invalid x86-64 argument pair!");
2695ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy)
const {
2698 X86_64ABIInfo::Class Lo, Hi;
2699 classify(RetTy, 0, Lo, Hi,
true);
2702 assert((Hi != Memory || Lo == Memory) &&
"Invalid memory classification.");
2703 assert((Hi != SSEUp || Lo == SSE) &&
"Invalid SSEUp classification.");
2705 llvm::Type *ResType =
nullptr;
2712 assert((Hi == SSE || Hi ==
Integer || Hi == X87Up) &&
2713 "Unknown missing lo part");
2718 llvm_unreachable(
"Invalid classification for lo word.");
2723 return getIndirectReturnResult(RetTy);
2728 ResType = GetINTEGERTypeAtOffset(CGT.ConvertType(RetTy), 0, RetTy, 0);
2735 RetTy = ED->getIntegerType();
2738 isPromotableIntegerTypeForABI(RetTy))
2742 if (ResType->isIntegerTy(128)) {
2752 ResType = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 0, RetTy, 0);
2758 ResType = llvm::Type::getX86_FP80Ty(getVMContext());
2765 assert(Hi == ComplexX87 &&
"Unexpected ComplexX87 classification.");
2766 ResType = llvm::StructType::get(llvm::Type::getX86_FP80Ty(getVMContext()),
2767 llvm::Type::getX86_FP80Ty(getVMContext()));
2771 llvm::Type *HighPart =
nullptr;
2777 llvm_unreachable(
"Invalid classification for hi word.");
2784 HighPart = GetINTEGERTypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8);
2789 HighPart = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8);
2800 assert(Lo == SSE &&
"Unexpected SSEUp classification.");
2801 ResType = GetByteVectorType(RetTy);
2812 HighPart = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8);
2829X86_64ABIInfo::classifyArgumentType(QualType Ty,
unsigned freeIntRegs,
2830 unsigned &neededInt,
unsigned &neededSSE,
2831 bool isNamedArg,
bool IsRegCall)
const {
2834 X86_64ABIInfo::Class Lo, Hi;
2835 classify(Ty, 0, Lo, Hi, isNamedArg, IsRegCall);
2839 assert((Hi != Memory || Lo == Memory) &&
"Invalid memory classification.");
2840 assert((Hi != SSEUp || Lo == SSE) &&
"Invalid SSEUp classification.");
2844 llvm::Type *ResType =
nullptr;
2851 assert((Hi == SSE || Hi ==
Integer || Hi == X87Up) &&
2852 "Unknown missing lo part");
2865 return getIndirectResult(Ty, freeIntRegs);
2869 llvm_unreachable(
"Invalid classification for lo word.");
2878 ResType = GetINTEGERTypeAtOffset(CGT.ConvertType(Ty), 0, Ty, 0);
2885 Ty = ED->getIntegerType();
2888 isPromotableIntegerTypeForABI(Ty))
2892 if (ResType->isIntegerTy(128)) {
2903 llvm::Type *IRType = CGT.ConvertType(Ty);
2904 ResType = GetSSETypeAtOffset(IRType, 0, Ty, 0);
2910 llvm::Type *HighPart =
nullptr;
2918 llvm_unreachable(
"Invalid classification for hi word.");
2920 case NoClass:
break;
2925 HighPart = GetINTEGERTypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8);
2936 HighPart = GetSSETypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8);
2946 assert(Lo == SSE &&
"Unexpected SSEUp classification");
2947 ResType = GetByteVectorType(Ty);
2964bool X86_64ABIInfo::passRegCallStructTypeDirectly(
2965 QualType Ty, SmallVectorImpl<llvm::Type *> &CoerceElts,
unsigned &NeededInt,
2966 unsigned &NeededSSE,
unsigned &MaxVectorWidth)
const {
2974 if (
auto CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2975 if (CXXRD->isDynamicClass())
2978 for (
const auto &I : CXXRD->bases()) {
2979 QualType BaseTy = I.getType();
2982 if (!passRegCallStructTypeDirectly(BaseTy, CoerceElts, NeededInt,
2983 NeededSSE, MaxVectorWidth))
2989 for (
const auto *FD : RD->
fields()) {
2994 if (!passRegCallStructTypeDirectly(MTy, CoerceElts, NeededInt, NeededSSE,
3000 const auto *AT = getContext().getAsConstantArrayType(MTy);
3002 MTy = AT->getElementType();
3004 unsigned LocalNeededInt, LocalNeededSSE;
3006 LocalNeededSSE,
true,
true);
3013 assert(CoerceTy &&
"ABI info for struct member has no coerce type");
3015 uint64_t NumElts = AT->getZExtSize();
3016 LocalNeededInt *= NumElts;
3017 LocalNeededSSE *= NumElts;
3018 CoerceElts.push_back(llvm::ArrayType::get(CoerceTy, NumElts));
3020 CoerceElts.push_back(CoerceTy);
3023 if (
const auto *VT = MTy->
getAs<VectorType>())
3024 if (getContext().getTypeSize(VT) > MaxVectorWidth)
3025 MaxVectorWidth = getContext().getTypeSize(VT);
3027 NeededInt += LocalNeededInt;
3028 NeededSSE += LocalNeededSSE;
3035X86_64ABIInfo::classifyRegCallStructType(QualType Ty,
unsigned &NeededInt,
3036 unsigned &NeededSSE,
3037 unsigned &MaxVectorWidth)
const {
3045 SmallVector<llvm::Type *, 16> CoerceElts;
3046 if (!passRegCallStructTypeDirectly(Ty, CoerceElts, NeededInt, NeededSSE,
3048 NeededInt = NeededSSE = 0;
3049 return getIndirectReturnResult(Ty);
3052 assert(!CoerceElts.empty() &&
"Non-empty struct produced no element types");
3054 llvm::StructType::get(getVMContext(), CoerceElts));
3058X86_64ABIInfo::getX86ABIAVXLevel(
const FunctionDecl *FD,
3059 const FunctionType::ExtInfo &Info)
const {
3063void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI)
const {
3069 WinX86_64ABIInfo Win64ABIInfo(CGT, AVXLevel);
3070 Win64ABIInfo.computeInfo(FI);
3075 static_cast<unsigned>(X86AVXABILevel::AVX512) &&
3076 "Unexpected X86 AVX ABI level");
3079 if (EffectiveAVXLevel != AVXLevel) {
3080 X86_64ABIInfo EffectiveABIInfo(CGT, EffectiveAVXLevel);
3081 EffectiveABIInfo.computeInfo(FI);
3085 bool IsRegCall =
CallingConv == llvm::CallingConv::X86_RegCall;
3088 unsigned FreeIntRegs = IsRegCall ? 11 : 6;
3089 unsigned FreeSSERegs = IsRegCall ? 16 : 8;
3090 unsigned NeededInt = 0, NeededSSE = 0, MaxVectorWidth = 0;
3097 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
3098 FreeIntRegs -= NeededInt;
3099 FreeSSERegs -= NeededSSE;
3105 ->
getAs<ComplexType>()
3106 ->getElementType()) ==
3107 getContext().LongDoubleTy)
3119 else if (NeededSSE && MaxVectorWidth > 0)
3135 it != ie; ++it, ++ArgNo) {
3136 bool IsNamedArg = ArgNo < NumRequiredArgs;
3138 if (IsRegCall && it->type->isStructureOrClassType())
3139 it->info = classifyRegCallStructType(it->type, NeededInt, NeededSSE,
3143 NeededSSE, IsNamedArg);
3149 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
3150 FreeIntRegs -= NeededInt;
3151 FreeSSERegs -= NeededSSE;
3155 it->info = getIndirectResult(it->type, FreeIntRegs);
3164 llvm::Value *overflow_arg_area =
3179 llvm::Value *Res = overflow_arg_area;
3186 uint64_t SizeInBytes = (CGF.
getContext().getTypeSize(Ty) + 7) / 8;
3187 llvm::Value *Offset =
3188 llvm::ConstantInt::get(CGF.
Int32Ty, (SizeInBytes + 7) & ~7);
3190 Offset,
"overflow_arg_area.next");
3194 return Address(Res, LTy, Align);
3197RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
3198 QualType Ty, AggValueSlot Slot)
const {
3206 unsigned neededInt, neededSSE;
3218 if (!neededInt && !neededSSE)
3234 llvm::Value *InRegs =
nullptr;
3236 llvm::Value *gp_offset =
nullptr, *fp_offset =
nullptr;
3240 InRegs = llvm::ConstantInt::get(CGF.
Int32Ty, 48 - neededInt * 8);
3241 InRegs = CGF.
Builder.CreateICmpULE(gp_offset, InRegs,
"fits_in_gp");
3247 llvm::Value *FitsInFP =
3248 llvm::ConstantInt::get(CGF.
Int32Ty, 176 - neededSSE * 16);
3249 FitsInFP = CGF.
Builder.CreateICmpULE(fp_offset, FitsInFP,
"fits_in_fp");
3250 InRegs = InRegs ? CGF.
Builder.CreateAnd(InRegs, FitsInFP) : FitsInFP;
3256 CGF.
Builder.CreateCondBr(InRegs, InRegBlock, InMemBlock);
3277 if (neededInt && neededSSE) {
3279 assert(AI.
isDirect() &&
"Unexpected ABI info for mixed regs");
3283 assert(ST->getNumElements() == 2 &&
"Unexpected ABI info for mixed regs");
3284 llvm::Type *TyLo = ST->getElementType(0);
3285 llvm::Type *TyHi = ST->getElementType(1);
3286 assert((TyLo->isFPOrFPVectorTy() ^ TyHi->isFPOrFPVectorTy()) &&
3287 "Unexpected ABI info for mixed regs");
3288 llvm::Value *GPAddr =
3290 llvm::Value *FPAddr =
3292 llvm::Value *RegLoAddr = TyLo->isFPOrFPVectorTy() ? FPAddr : GPAddr;
3293 llvm::Value *RegHiAddr = TyLo->isFPOrFPVectorTy() ? GPAddr : FPAddr;
3309 }
else if (neededInt || neededSSE == 1) {
3311 auto TInfo = getContext().getTypeInfoInChars(Ty);
3312 uint64_t TySize = TInfo.Width.getQuantity();
3313 CharUnits TyAlign = TInfo.Align;
3314 llvm::Type *CoTy =
nullptr;
3318 llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset;
3319 uint64_t Alignment = neededInt ? 8 : 16;
3320 uint64_t RegSize = neededInt ? neededInt * 8 : 16;
3345 llvm::Value *PtrOffset =
3367 assert(neededSSE == 2 &&
"Invalid number of needed registers!");
3400 llvm::Value *Offset = llvm::ConstantInt::get(CGF.
Int32Ty, neededInt * 8);
3405 llvm::Value *Offset = llvm::ConstantInt::get(CGF.
Int32Ty, neededSSE * 16);
3424RValue X86_64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
3425 QualType Ty, AggValueSlot Slot)
const {
3428 uint64_t Width = getContext().getTypeSize(Ty);
3429 bool IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
3437ABIArgInfo WinX86_64ABIInfo::reclassifyHvaArgForVectorCall(
3438 QualType Ty,
unsigned &FreeSSERegs,
const ABIArgInfo ¤t)
const {
3443 isHomogeneousAggregate(Ty, Base, NumElts) && FreeSSERegs >= NumElts) {
3444 FreeSSERegs -= NumElts;
3445 return getDirectX86Hva();
3450ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty,
unsigned &FreeSSERegs,
3451 bool IsReturnType,
unsigned CC)
const {
3452 bool IsVectorCall = CC == llvm::CallingConv::X86_VectorCall;
3453 bool IsRegCall = CC == llvm::CallingConv::X86_RegCall;
3459 Ty = ED->getIntegerType();
3461 TypeInfo Info = getContext().getTypeInfo(Ty);
3463 CharUnits Align = getContext().toCharUnitsFromBits(Info.
Align);
3467 if (!IsReturnType) {
3469 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
3473 if (RT->getDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())
3474 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
3482 if ((IsVectorCall || IsRegCall) &&
3483 isHomogeneousAggregate(Ty, Base, NumElts)) {
3485 if (FreeSSERegs >= NumElts) {
3486 FreeSSERegs -= NumElts;
3492 Align, getDataLayout().getAllocaAddrSpace(),
3494 }
else if (IsVectorCall) {
3495 if (FreeSSERegs >= NumElts &&
3497 FreeSSERegs -= NumElts;
3499 }
else if (IsReturnType) {
3504 Align, getDataLayout().getAllocaAddrSpace(),
3513 llvm::Type *LLTy = CGT.ConvertType(Ty);
3514 if (LLTy->isPointerTy() || LLTy->isIntegerTy())
3521 if (Width > 64 || !llvm::isPowerOf2_64(Width))
3522 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
3529 if (
const BuiltinType *BT = Ty->
getAs<BuiltinType>()) {
3530 switch (BT->getKind()) {
3531 case BuiltinType::Bool:
3536 case BuiltinType::LongDouble:
3540 const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
3541 if (LDF == &llvm::APFloat::x87DoubleExtended())
3543 Align, getDataLayout().getAllocaAddrSpace(),
3548 case BuiltinType::Int128:
3549 case BuiltinType::UInt128:
3550 case BuiltinType::Float128:
3556 Align, getDataLayout().getAllocaAddrSpace(),
3561 if (BT->getKind() == BuiltinType::Int128 ||
3562 BT->getKind() == BuiltinType::UInt128)
3564 llvm::Type::getInt64Ty(getVMContext()), 2));
3568 if (BT->getKind() == BuiltinType::Float128) {
3569 auto IsWin64F128StackCC = [
this](
unsigned CC) ->
bool {
3571 case llvm::CallingConv::Win64:
3573 case llvm::CallingConv::C:
3574 return getTarget().getTriple().isOSWindowsOrUEFI();
3580 if (IsWin64F128StackCC(CC))
3581 return getNaturalAlignIndirect(
3582 Ty, getDataLayout().getAllocaAddrSpace(),
false);
3600 Align, getDataLayout().getAllocaAddrSpace(),
3608WinX86_64ABIInfo::getX86ABIAVXLevel(
const FunctionDecl *FD,
3609 const FunctionType::ExtInfo &Info)
const {
3614 return static_cast<unsigned>(AVXLevel);
3617void WinX86_64ABIInfo::computeInfo(CGFunctionInfo &FI)
const {
3619 bool IsVectorCall = CC == llvm::CallingConv::X86_VectorCall;
3620 bool IsRegCall = CC == llvm::CallingConv::X86_RegCall;
3624 if (CC == llvm::CallingConv::X86_64_SysV) {
3625 X86_64ABIInfo SysVABIInfo(CGT, AVXLevel);
3626 SysVABIInfo.computeInfo(FI);
3630 unsigned FreeSSERegs = 0;
3634 }
else if (IsRegCall) {
3645 }
else if (IsRegCall) {
3650 unsigned ArgNum = 0;
3651 unsigned ZeroSSERegs = 0;
3656 unsigned *MaybeFreeSSERegs =
3657 (IsVectorCall && ArgNum >= 6) ? &ZeroSSERegs : &FreeSSERegs;
3658 I.
info = classify(I.
type, *MaybeFreeSSERegs,
false, CC);
3666 I.
info = reclassifyHvaArgForVectorCall(I.
type, FreeSSERegs, I.
info);
3670RValue WinX86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
3671 QualType Ty, AggValueSlot Slot)
const {
3674 uint64_t Width = getContext().getTypeSize(Ty);
3675 bool IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
3684 CodeGenModule &CGM,
bool DarwinVectorABI,
bool Win32StructABI,
3685 unsigned NumRegisterParameters,
bool SoftFloatABI) {
3686 bool RetSmallStructInRegABI = X86_32TargetCodeGenInfo::isStructReturnInRegABI(
3688 return std::make_unique<X86_32TargetCodeGenInfo>(
3689 CGM.
getTypes(), DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI,
3690 NumRegisterParameters, SoftFloatABI);
3694 CodeGenModule &CGM,
bool DarwinVectorABI,
bool Win32StructABI,
3695 unsigned NumRegisterParameters) {
3696 bool RetSmallStructInRegABI = X86_32TargetCodeGenInfo::isStructReturnInRegABI(
3698 return std::make_unique<WinX86_32TargetCodeGenInfo>(
3699 CGM.
getTypes(), DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI,
3700 NumRegisterParameters);
3703std::unique_ptr<TargetCodeGenInfo>
3706 return std::make_unique<X86_64TargetCodeGenInfo>(CGM.
getTypes(), AVXLevel);
3709std::unique_ptr<TargetCodeGenInfo>
3712 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 getIndirect(CharUnits Alignment, unsigned AddrSpace, bool ByVal=true, bool Realign=false, llvm::Type *Padding=nullptr)
static ABIArgInfo getExtend(QualType Ty, llvm::Type *T=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 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.
The JSON file list parser is used to communicate input to InstallAPI.
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