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;
1389 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
1390 AggValueSlot Slot)
const override;
1391 RValue EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
1392 AggValueSlot Slot)
const override;
1394 bool has64BitPointers()
const {
1395 return Has64BitPointers;
1400class WinX86_64ABIInfo :
public ABIInfo {
1402 WinX86_64ABIInfo(CodeGen::CodeGenTypes &CGT,
X86AVXABILevel AVXLevel)
1403 : ABIInfo(CGT), AVXLevel(AVXLevel),
1404 IsMingw64(getTarget().
getTriple().isWindowsGNUEnvironment()) {}
1406 void computeInfo(CGFunctionInfo &FI)
const override;
1408 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
1409 AggValueSlot Slot)
const override;
1411 bool isHomogeneousAggregateBaseType(QualType Ty)
const override {
1413 return isX86VectorTypeForVectorCall(getContext(), Ty);
1416 bool isHomogeneousAggregateSmallEnough(
const Type *Ty,
1417 uint64_t NumMembers)
const override {
1419 return isX86VectorCallAggregateSmallEnough(NumMembers);
1422 ABIArgInfo classifyArgForArm64ECVarArg(QualType Ty)
const override {
1423 unsigned FreeSSERegs = 0;
1424 return classify(Ty, FreeSSERegs,
false,
1425 llvm::CallingConv::C);
1429 ABIArgInfo classify(QualType Ty,
unsigned &FreeSSERegs,
bool IsReturnType,
1431 ABIArgInfo reclassifyHvaArgForVectorCall(QualType Ty,
unsigned &FreeSSERegs,
1432 const ABIArgInfo ¤t)
const;
1439class X86_64TargetCodeGenInfo :
public TargetCodeGenInfo {
1441 X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
X86AVXABILevel AVXLevel)
1442 : TargetCodeGenInfo(std::make_unique<X86_64ABIInfo>(CGT, AVXLevel)) {
1444 std::make_unique<SwiftABIInfo>(CGT,
true);
1449 bool markARCOptimizedReturnCallsAsNoTail()
const override {
return true; }
1451 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM)
const override {
1455 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
1456 llvm::Value *Address)
const override {
1457 llvm::Value *Eight8 = llvm::ConstantInt::get(CGF.
Int8Ty, 8);
1465 llvm::Type* adjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
1466 StringRef Constraint,
1467 llvm::Type* Ty)
const override {
1468 return X86AdjustInlineAsmType(CGF, Constraint, Ty);
1471 bool isNoProtoCallVariadic(
const CallArgList &args,
1472 const FunctionNoProtoType *fnType)
const override {
1480 bool HasAVXType =
false;
1481 for (
const CallArg &arg : args) {
1482 if (getABIInfo<X86_64ABIInfo>().isPassedUsingAVXType(
arg.Ty)) {
1495 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1496 CodeGen::CodeGenModule &CGM)
const override {
1497 if (GV->isDeclaration())
1499 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
1500 if (FD->hasAttr<X86ForceAlignArgPointerAttr>()) {
1502 Fn->addFnAttr(
"stackrealign");
1509 void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc,
1510 const FunctionDecl *Caller,
1511 const FunctionDecl *Callee,
const CallArgList &Args,
1512 QualType ReturnType)
const override;
1514 void checkFunctionABI(CodeGenModule &CGM,
1515 const FunctionDecl *FD)
const override;
1520 llvm::StringMap<bool> &CallerMap,
1522 llvm::StringMap<bool> &CalleeMap,
1524 if (CalleeMap.empty() && CallerMap.empty()) {
1536 const llvm::StringMap<bool> &CallerMap,
1537 const llvm::StringMap<bool> &CalleeMap,
1540 bool CallerHasFeat = CallerMap.lookup(
Feature);
1541 bool CalleeHasFeat = CalleeMap.lookup(
Feature);
1543 if (!CallerHasFeat && !CalleeHasFeat &&
1544 (!Callee.isExternallyVisible() || Callee.hasAttr<AlwaysInlineAttr>()))
1547 if (!CallerHasFeat && !CalleeHasFeat)
1548 return Diag.Report(CallLoc, diag::warn_avx_calling_convention)
1549 << IsArgument << Ty <<
Feature;
1552 if (!CallerHasFeat || !CalleeHasFeat)
1553 return Diag.Report(CallLoc, diag::err_avx_calling_convention)
1554 << IsArgument << Ty <<
Feature;
1563 const llvm::StringMap<bool> &CallerMap,
1564 const llvm::StringMap<bool> &CalleeMap,
QualType Ty,
1569 "avx512f", IsArgument);
1578void X86_64TargetCodeGenInfo::checkFunctionABI(CodeGenModule &CGM,
1579 const FunctionDecl *FD)
const {
1580 auto GetReturnTypeLoc = [](
const FunctionDecl *FD) {
1582 TypeLoc TL = TSI->getTypeLoc();
1585 SourceLocation Loc = FTL.getReturnLoc().getBeginLoc();
1598 auto Check = [&](QualType Ty, SourceLocation Loc,
bool IsReturn) {
1607 llvm::StringMap<bool> FeatureMap;
1609 if (!FeatureMap.lookup(
Feature)) {
1611 << !IsReturn << Ty <<
Feature;
1628 for (
const ParmVarDecl *P : FD->
parameters()) {
1629 SourceLocation Loc = P->getLocation();
1631 Loc = P->getBeginLoc();
1632 if (Check(P->getType(), Loc,
false))
1637void X86_64TargetCodeGenInfo::checkFunctionCallABI(CodeGenModule &CGM,
1638 SourceLocation CallLoc,
1639 const FunctionDecl *Caller,
1640 const FunctionDecl *Callee,
1641 const CallArgList &Args,
1642 QualType ReturnType)
const {
1646 llvm::StringMap<bool> CallerMap;
1647 llvm::StringMap<bool> CalleeMap;
1648 unsigned ArgIndex = 0;
1652 for (
const CallArg &Arg : Args) {
1660 if (Arg.getType()->isVectorType() &&
1663 QualType Ty = Arg.getType();
1666 if (ArgIndex < Callee->getNumParams())
1667 Ty =
Callee->getParamDecl(ArgIndex)->getType();
1670 CallerMap, CalleeMap, Ty,
true))
1678 if (
Callee->getReturnType()->isVectorType() &&
1682 CalleeMap,
Callee->getReturnType(),
1691 bool Quote = Lib.contains(
' ');
1692 std::string ArgStr = Quote ?
"\"" :
"";
1694 if (!Lib.ends_with_insensitive(
".lib") && !Lib.ends_with_insensitive(
".a"))
1696 ArgStr += Quote ?
"\"" :
"";
1701class WinX86_32TargetCodeGenInfo :
public X86_32TargetCodeGenInfo {
1704 bool DarwinVectorABI,
bool RetSmallStructInRegABI,
bool Win32StructABI,
1705 unsigned NumRegisterParameters)
1706 : X86_32TargetCodeGenInfo(CGT, DarwinVectorABI, RetSmallStructInRegABI,
1707 Win32StructABI, NumRegisterParameters,
false) {}
1709 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1712 void getDependentLibraryOption(llvm::StringRef Lib,
1714 Opt =
"/DEFAULTLIB:";
1715 Opt += qualifyWindowsLibrary(Lib);
1718 void getDetectMismatchOption(llvm::StringRef Name,
1719 llvm::StringRef
Value,
1721 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
1726void WinX86_32TargetCodeGenInfo::setTargetAttributes(
1727 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM)
const {
1728 X86_32TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
1729 if (GV->isDeclaration())
1731 addStackProbeTargetAttributes(D, GV, CGM);
1735class WinX86_64TargetCodeGenInfo :
public TargetCodeGenInfo {
1737 WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
1739 : TargetCodeGenInfo(std::make_unique<WinX86_64ABIInfo>(CGT, AVXLevel)) {
1741 std::make_unique<SwiftABIInfo>(CGT,
true);
1744 void setTargetAttributes(
const Decl *D, llvm::GlobalValue *GV,
1745 CodeGen::CodeGenModule &CGM)
const override;
1747 int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM)
const override {
1751 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
1752 llvm::Value *Address)
const override {
1753 llvm::Value *Eight8 = llvm::ConstantInt::get(CGF.
Int8Ty, 8);
1761 void getDependentLibraryOption(llvm::StringRef Lib,
1762 llvm::SmallString<24> &Opt)
const override {
1763 Opt =
"/DEFAULTLIB:";
1764 Opt += qualifyWindowsLibrary(Lib);
1767 void getDetectMismatchOption(llvm::StringRef Name,
1768 llvm::StringRef
Value,
1769 llvm::SmallString<32> &Opt)
const override {
1770 Opt =
"/FAILIFMISMATCH:\"" + Name.str() +
"=" +
Value.str() +
"\"";
1775void WinX86_64TargetCodeGenInfo::setTargetAttributes(
1776 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM)
const {
1778 if (GV->isDeclaration())
1780 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
1781 if (FD->
hasAttr<X86ForceAlignArgPointerAttr>()) {
1783 Fn->addFnAttr(
"stackrealign");
1789 addStackProbeTargetAttributes(D, GV, CGM);
1792void X86_64ABIInfo::postMerge(
unsigned AggregateSize,
Class &Lo,
1817 if (Hi == X87Up && Lo != X87 && honorsRevision0_98())
1819 if (AggregateSize > 128 && (Lo != SSE || Hi != SSEUp))
1821 if (Hi == SSEUp && Lo != SSE)
1825X86_64ABIInfo::Class X86_64ABIInfo::merge(
Class Accum,
Class Field) {
1849 assert((Accum != Memory && Accum != ComplexX87) &&
1850 "Invalid accumulated classification during merge.");
1851 if (Accum == Field || Field == NoClass)
1853 if (Field == Memory)
1855 if (Accum == NoClass)
1859 if (Field == X87 || Field == X87Up || Field == ComplexX87 ||
1860 Accum == X87 || Accum == X87Up)
1865void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
Class &Lo,
1866 Class &Hi,
bool isNamedArg,
bool IsRegCall)
const {
1877 Class &Current = OffsetBase < 64 ? Lo : Hi;
1880 if (
const BuiltinType *BT = Ty->
getAs<BuiltinType>()) {
1883 if (k == BuiltinType::Void) {
1885 }
else if (k == BuiltinType::Int128 || k == BuiltinType::UInt128) {
1888 }
else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
1890 }
else if (k == BuiltinType::Float || k == BuiltinType::Double ||
1891 k == BuiltinType::Float16 || k == BuiltinType::BFloat16) {
1893 }
else if (k == BuiltinType::Float128) {
1896 }
else if (k == BuiltinType::LongDouble) {
1897 const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
1898 if (LDF == &llvm::APFloat::IEEEquad()) {
1901 }
else if (LDF == &llvm::APFloat::x87DoubleExtended()) {
1904 }
else if (LDF == &llvm::APFloat::IEEEdouble()) {
1907 llvm_unreachable(
"unexpected long double representation!");
1916 classify(ED->getIntegerType(), OffsetBase, Lo, Hi, isNamedArg);
1927 if (Has64BitPointers) {
1934 uint64_t EB_FuncPtr = (OffsetBase) / 64;
1935 uint64_t EB_ThisAdj = (OffsetBase + 64 - 1) / 64;
1936 if (EB_FuncPtr != EB_ThisAdj) {
1948 if (
const VectorType *VT = Ty->
getAs<VectorType>()) {
1950 if (Size == 1 || Size == 8 || Size == 16 || Size == 32) {
1959 uint64_t EB_Lo = (OffsetBase) / 64;
1963 }
else if (Size == 64) {
1964 QualType ElementType = VT->getElementType();
1973 if (!classifyIntegerMMXAsSSE() &&
1984 if (OffsetBase && OffsetBase != 64)
1986 }
else if (Size == 128 ||
1987 (isNamedArg && Size <= getNativeVectorSizeForAVXABI(AVXLevel))) {
1988 QualType ElementType = VT->getElementType();
1991 if (passInt128VectorsInMem() && Size != 128 &&
2016 if (
const ComplexType *CT = Ty->
getAs<ComplexType>()) {
2023 else if (Size <= 128)
2025 }
else if (ET->
isFloat16Type() || ET == getContext().FloatTy ||
2028 }
else if (ET == getContext().DoubleTy) {
2030 }
else if (ET == getContext().LongDoubleTy) {
2031 const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
2032 if (LDF == &llvm::APFloat::IEEEquad())
2034 else if (LDF == &llvm::APFloat::x87DoubleExtended())
2035 Current = ComplexX87;
2036 else if (LDF == &llvm::APFloat::IEEEdouble())
2039 llvm_unreachable(
"unexpected long double representation!");
2044 uint64_t EB_Real = (OffsetBase) / 64;
2045 uint64_t EB_Imag = (OffsetBase + getContext().getTypeSize(ET)) / 64;
2046 if (Hi == NoClass && EB_Real != EB_Imag)
2052 if (
const auto *EITy = Ty->
getAs<BitIntType>()) {
2053 if (EITy->getNumBits() <= 64)
2055 else if (EITy->getNumBits() <= 128)
2061 if (
const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
2070 if (!IsRegCall && Size > 512)
2077 if (OffsetBase % getContext().getTypeAlign(AT->getElementType()))
2083 uint64_t EltSize = getContext().getTypeSize(AT->getElementType());
2084 uint64_t ArraySize = AT->getZExtSize();
2091 (Size != EltSize || Size > getNativeVectorSizeForAVXABI(AVXLevel)))
2094 for (uint64_t i=0, Offset=OffsetBase; i<ArraySize; ++i, Offset += EltSize) {
2095 Class FieldLo, FieldHi;
2096 classify(AT->getElementType(), Offset, FieldLo, FieldHi, isNamedArg);
2097 Lo =
merge(Lo, FieldLo);
2098 Hi =
merge(Hi, FieldHi);
2099 if (Lo == Memory || Hi == Memory)
2103 postMerge(Size, Lo, Hi);
2104 assert((Hi != SSEUp || Lo == SSE) &&
"Invalid SSEUp array classification.");
2128 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
2134 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2135 for (
const auto &I : CXXRD->bases()) {
2136 assert(!I.isVirtual() && !I.getType()->isDependentType() &&
2137 "Unexpected base class!");
2138 const auto *
Base = I.getType()->castAsCXXRecordDecl();
2144 Class FieldLo, FieldHi;
2147 classify(I.getType(), Offset, FieldLo, FieldHi, isNamedArg);
2148 Lo =
merge(Lo, FieldLo);
2149 Hi =
merge(Hi, FieldHi);
2150 if (returnCXXRecordGreaterThan128InMem() &&
2152 (Size > 128 && (Size != getContext().getTypeSize(I.getType()) ||
2153 Size > getNativeVectorSizeForAVXABI(AVXLevel)))) {
2158 if (Lo == Memory || Hi == Memory) {
2159 postMerge(Size, Lo, Hi);
2167 bool UseClang11Compat = getContext().getLangOpts().isCompatibleWith(
2168 LangOptions::ClangABI::Ver11) ||
2169 getContext().getTargetInfo().getTriple().isPS();
2170 bool IsUnion = RT->isUnionType() && !UseClang11Compat;
2173 i != e; ++i, ++idx) {
2175 bool BitField = i->isBitField();
2178 if (BitField && i->isUnnamedBitField())
2191 ((!IsUnion && Size != getContext().getTypeSize(i->getType())) ||
2192 Size > getNativeVectorSizeForAVXABI(AVXLevel))) {
2194 postMerge(Size, Lo, Hi);
2199 Offset % getContext().getTypeAlign(i->getType().getCanonicalType());
2201 if (!BitField && IsInMemory) {
2203 postMerge(Size, Lo, Hi);
2213 Class FieldLo, FieldHi;
2219 assert(!i->isUnnamedBitField());
2227 assert(EB_Hi == EB_Lo &&
"Invalid classification, type > 16 bytes.");
2232 FieldHi = EB_Hi ?
Integer : NoClass;
2235 classify(i->getType(), Offset, FieldLo, FieldHi, isNamedArg);
2236 Lo =
merge(Lo, FieldLo);
2237 Hi =
merge(Hi, FieldHi);
2238 if (Lo == Memory || Hi == Memory)
2242 postMerge(Size, Lo, Hi);
2246ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty)
const {
2252 Ty = ED->getIntegerType();
2255 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
2257 llvm::Type *IRTy = CGT.ConvertType(Ty);
2262 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
2265bool X86_64ABIInfo::IsIllegalVectorType(QualType Ty)
const {
2266 if (
const VectorType *VecTy = Ty->
getAs<VectorType>()) {
2268 unsigned LargestVector = getNativeVectorSizeForAVXABI(AVXLevel);
2269 if (Size <= 64 || Size > LargestVector)
2271 QualType EltTy = VecTy->getElementType();
2272 if (passInt128VectorsInMem() &&
2281ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty,
2282 unsigned freeIntRegs)
const {
2295 Ty = ED->getIntegerType();
2297 llvm::Type *IRTy = CGT.ConvertType(Ty);
2303 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
2308 unsigned Align = std::max(getContext().getTypeAlign(Ty) / 8, 8U);
2331 if (freeIntRegs == 0) {
2336 if (Align == 8 && Size <= 64)
2342 getDataLayout().getAllocaAddrSpace());
2347llvm::Type *X86_64ABIInfo::GetByteVectorType(QualType Ty)
const {
2351 Ty = QualType(InnerTy, 0);
2353 llvm::Type *IRType = CGT.ConvertType(Ty);
2357 if (passInt128VectorsInMem() &&
2361 return llvm::FixedVectorType::get(llvm::Type::getInt64Ty(getVMContext()),
2368 if (IRType->getTypeID() == llvm::Type::FP128TyID)
2373 assert((Size == 128 || Size == 256 || Size == 512) &&
"Invalid type found!");
2377 return llvm::FixedVectorType::get(llvm::Type::getDoubleTy(getVMContext()),
2393 unsigned TySize = (
unsigned)Context.getTypeSize(Ty);
2394 if (TySize <= StartBit)
2398 unsigned EltSize = (
unsigned)Context.getTypeSize(AT->getElementType());
2399 unsigned NumElts = (
unsigned)AT->getZExtSize();
2402 for (
unsigned i = 0; i != NumElts; ++i) {
2404 unsigned EltOffset = i*EltSize;
2405 if (EltOffset >= EndBit)
break;
2407 unsigned EltStart = EltOffset < StartBit ? StartBit-EltOffset :0;
2409 EndBit-EltOffset, Context))
2420 if (
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2421 for (
const auto &I : CXXRD->bases()) {
2422 assert(!I.isVirtual() && !I.getType()->isDependentType() &&
2423 "Unexpected base class!");
2424 const auto *
Base = I.getType()->castAsCXXRecordDecl();
2428 if (BaseOffset >= EndBit)
continue;
2430 unsigned BaseStart = BaseOffset < StartBit ? StartBit-BaseOffset :0;
2432 EndBit-BaseOffset, Context))
2443 i != e; ++i, ++idx) {
2447 if (FieldOffset >= EndBit)
break;
2449 unsigned FieldStart = FieldOffset < StartBit ? StartBit-FieldOffset :0;
2465 const llvm::DataLayout &TD) {
2466 if (IROffset == 0 && IRType->isFloatingPointTy())
2470 if (llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) {
2471 if (!STy->getNumContainedTypes())
2474 const llvm::StructLayout *SL = TD.getStructLayout(STy);
2475 unsigned Elt = SL->getElementContainingOffset(IROffset);
2476 IROffset -= SL->getElementOffset(Elt);
2481 if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) {
2482 llvm::Type *EltTy = ATy->getElementType();
2483 unsigned EltSize = TD.getTypeAllocSize(EltTy);
2484 IROffset -= IROffset / EltSize * EltSize;
2493llvm::Type *X86_64ABIInfo::
2494GetSSETypeAtOffset(llvm::Type *IRType,
unsigned IROffset,
2495 QualType SourceTy,
unsigned SourceOffset)
const {
2496 const llvm::DataLayout &TD = getDataLayout();
2497 unsigned SourceSize =
2498 (unsigned)getContext().getTypeSize(SourceTy) / 8 - SourceOffset;
2500 if (!T0 || T0->isDoubleTy())
2501 return llvm::Type::getDoubleTy(getVMContext());
2504 llvm::Type *T1 =
nullptr;
2505 unsigned T0Size = TD.getTypeAllocSize(T0);
2506 if (SourceSize > T0Size)
2508 if (T1 ==
nullptr) {
2511 if (T0->is16bitFPTy() && SourceSize > 4)
2520 if (T0->isFloatTy() && T1->isFloatTy())
2521 return llvm::FixedVectorType::get(T0, 2);
2523 if (T0->is16bitFPTy() && T1->is16bitFPTy()) {
2524 llvm::Type *T2 =
nullptr;
2528 return llvm::FixedVectorType::get(T0, 2);
2529 return llvm::FixedVectorType::get(T0, 4);
2532 if (T0->is16bitFPTy() || T1->is16bitFPTy())
2533 return llvm::FixedVectorType::get(llvm::Type::getHalfTy(getVMContext()), 4);
2535 return llvm::Type::getDoubleTy(getVMContext());
2552llvm::Type *X86_64ABIInfo::
2553GetINTEGERTypeAtOffset(llvm::Type *IRType,
unsigned IROffset,
2554 QualType SourceTy,
unsigned SourceOffset)
const {
2557 if (IROffset == 0) {
2560 IRType->isIntegerTy(64))
2569 if (IRType->isIntegerTy(8) || IRType->isIntegerTy(16) ||
2570 IRType->isIntegerTy(32) ||
2576 SourceOffset*8+64, getContext()))
2581 if (llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) {
2583 const llvm::StructLayout *SL = getDataLayout().getStructLayout(STy);
2584 if (IROffset < SL->getSizeInBytes()) {
2585 unsigned FieldIdx = SL->getElementContainingOffset(IROffset);
2586 IROffset -= SL->getElementOffset(FieldIdx);
2588 return GetINTEGERTypeAtOffset(STy->getElementType(FieldIdx), IROffset,
2589 SourceTy, SourceOffset);
2593 if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) {
2594 llvm::Type *EltTy = ATy->getElementType();
2595 unsigned EltSize = getDataLayout().getTypeAllocSize(EltTy);
2596 unsigned EltOffset = IROffset/EltSize*EltSize;
2597 return GetINTEGERTypeAtOffset(EltTy, IROffset-EltOffset, SourceTy,
2603 if (IRType->isIntegerTy(128)) {
2604 assert(IROffset == 0);
2610 unsigned TySizeInBytes =
2611 (unsigned)getContext().getTypeSizeInChars(SourceTy).getQuantity();
2613 assert(TySizeInBytes != SourceOffset &&
"Empty field?");
2617 return llvm::IntegerType::get(getVMContext(),
2618 std::min(TySizeInBytes-SourceOffset, 8U)*8);
2629 const llvm::DataLayout &TD) {
2634 unsigned LoSize = (
unsigned)TD.getTypeAllocSize(Lo);
2635 llvm::Align HiAlign = TD.getABITypeAlign(Hi);
2636 unsigned HiStart = llvm::alignTo(LoSize, HiAlign);
2637 assert(HiStart != 0 && HiStart <= 8 &&
"Invalid x86-64 argument pair!");
2648 if (Lo->isHalfTy() || Lo->isFloatTy())
2649 Lo = llvm::Type::getDoubleTy(Lo->getContext());
2651 assert((Lo->isIntegerTy() || Lo->isPointerTy())
2652 &&
"Invalid/unknown lo type");
2653 Lo = llvm::Type::getInt64Ty(Lo->getContext());
2657 llvm::StructType *
Result = llvm::StructType::get(Lo, Hi);
2660 assert(TD.getStructLayout(
Result)->getElementOffset(1) == 8 &&
2661 "Invalid x86-64 argument pair!");
2665ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy)
const {
2668 X86_64ABIInfo::Class Lo, Hi;
2669 classify(RetTy, 0, Lo, Hi,
true);
2672 assert((Hi != Memory || Lo == Memory) &&
"Invalid memory classification.");
2673 assert((Hi != SSEUp || Lo == SSE) &&
"Invalid SSEUp classification.");
2675 llvm::Type *ResType =
nullptr;
2682 assert((Hi == SSE || Hi ==
Integer || Hi == X87Up) &&
2683 "Unknown missing lo part");
2688 llvm_unreachable(
"Invalid classification for lo word.");
2693 return getIndirectReturnResult(RetTy);
2698 ResType = GetINTEGERTypeAtOffset(CGT.ConvertType(RetTy), 0, RetTy, 0);
2705 RetTy = ED->getIntegerType();
2708 isPromotableIntegerTypeForABI(RetTy))
2712 if (ResType->isIntegerTy(128)) {
2722 ResType = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 0, RetTy, 0);
2728 ResType = llvm::Type::getX86_FP80Ty(getVMContext());
2735 assert(Hi == ComplexX87 &&
"Unexpected ComplexX87 classification.");
2736 ResType = llvm::StructType::get(llvm::Type::getX86_FP80Ty(getVMContext()),
2737 llvm::Type::getX86_FP80Ty(getVMContext()));
2741 llvm::Type *HighPart =
nullptr;
2747 llvm_unreachable(
"Invalid classification for hi word.");
2754 HighPart = GetINTEGERTypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8);
2759 HighPart = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8);
2770 assert(Lo == SSE &&
"Unexpected SSEUp classification.");
2771 ResType = GetByteVectorType(RetTy);
2782 HighPart = GetSSETypeAtOffset(CGT.ConvertType(RetTy), 8, RetTy, 8);
2799X86_64ABIInfo::classifyArgumentType(QualType Ty,
unsigned freeIntRegs,
2800 unsigned &neededInt,
unsigned &neededSSE,
2801 bool isNamedArg,
bool IsRegCall)
const {
2804 X86_64ABIInfo::Class Lo, Hi;
2805 classify(Ty, 0, Lo, Hi, isNamedArg, IsRegCall);
2809 assert((Hi != Memory || Lo == Memory) &&
"Invalid memory classification.");
2810 assert((Hi != SSEUp || Lo == SSE) &&
"Invalid SSEUp classification.");
2814 llvm::Type *ResType =
nullptr;
2821 assert((Hi == SSE || Hi ==
Integer || Hi == X87Up) &&
2822 "Unknown missing lo part");
2835 return getIndirectResult(Ty, freeIntRegs);
2839 llvm_unreachable(
"Invalid classification for lo word.");
2848 ResType = GetINTEGERTypeAtOffset(CGT.ConvertType(Ty), 0, Ty, 0);
2855 Ty = ED->getIntegerType();
2858 isPromotableIntegerTypeForABI(Ty))
2862 if (ResType->isIntegerTy(128)) {
2873 llvm::Type *IRType = CGT.ConvertType(Ty);
2874 ResType = GetSSETypeAtOffset(IRType, 0, Ty, 0);
2880 llvm::Type *HighPart =
nullptr;
2888 llvm_unreachable(
"Invalid classification for hi word.");
2890 case NoClass:
break;
2895 HighPart = GetINTEGERTypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8);
2906 HighPart = GetSSETypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8);
2916 assert(Lo == SSE &&
"Unexpected SSEUp classification");
2917 ResType = GetByteVectorType(Ty);
2934bool X86_64ABIInfo::passRegCallStructTypeDirectly(
2935 QualType Ty, SmallVectorImpl<llvm::Type *> &CoerceElts,
unsigned &NeededInt,
2936 unsigned &NeededSSE,
unsigned &MaxVectorWidth)
const {
2944 if (
auto CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
2945 if (CXXRD->isDynamicClass())
2948 for (
const auto &I : CXXRD->bases()) {
2949 QualType BaseTy = I.getType();
2952 if (!passRegCallStructTypeDirectly(BaseTy, CoerceElts, NeededInt,
2953 NeededSSE, MaxVectorWidth))
2959 for (
const auto *FD : RD->
fields()) {
2964 if (!passRegCallStructTypeDirectly(MTy, CoerceElts, NeededInt, NeededSSE,
2970 const auto *AT = getContext().getAsConstantArrayType(MTy);
2972 MTy = AT->getElementType();
2974 unsigned LocalNeededInt, LocalNeededSSE;
2976 LocalNeededSSE,
true,
true);
2983 assert(CoerceTy &&
"ABI info for struct member has no coerce type");
2985 uint64_t NumElts = AT->getZExtSize();
2986 LocalNeededInt *= NumElts;
2987 LocalNeededSSE *= NumElts;
2988 CoerceElts.push_back(llvm::ArrayType::get(CoerceTy, NumElts));
2990 CoerceElts.push_back(CoerceTy);
2993 if (
const auto *VT = MTy->
getAs<VectorType>())
2994 if (getContext().getTypeSize(VT) > MaxVectorWidth)
2995 MaxVectorWidth = getContext().getTypeSize(VT);
2997 NeededInt += LocalNeededInt;
2998 NeededSSE += LocalNeededSSE;
3005X86_64ABIInfo::classifyRegCallStructType(QualType Ty,
unsigned &NeededInt,
3006 unsigned &NeededSSE,
3007 unsigned &MaxVectorWidth)
const {
3015 SmallVector<llvm::Type *, 16> CoerceElts;
3016 if (!passRegCallStructTypeDirectly(Ty, CoerceElts, NeededInt, NeededSSE,
3018 NeededInt = NeededSSE = 0;
3019 return getIndirectReturnResult(Ty);
3022 assert(!CoerceElts.empty() &&
"Non-empty struct produced no element types");
3024 llvm::StructType::get(getVMContext(), CoerceElts));
3027void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI)
const {
3034 WinX86_64ABIInfo Win64ABIInfo(CGT, AVXLevel);
3035 Win64ABIInfo.computeInfo(FI);
3039 bool IsRegCall =
CallingConv == llvm::CallingConv::X86_RegCall;
3042 unsigned FreeIntRegs = IsRegCall ? 11 : 6;
3043 unsigned FreeSSERegs = IsRegCall ? 16 : 8;
3044 unsigned NeededInt = 0, NeededSSE = 0, MaxVectorWidth = 0;
3051 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
3052 FreeIntRegs -= NeededInt;
3053 FreeSSERegs -= NeededSSE;
3059 ->
getAs<ComplexType>()
3060 ->getElementType()) ==
3061 getContext().LongDoubleTy)
3073 else if (NeededSSE && MaxVectorWidth > 0)
3089 it != ie; ++it, ++ArgNo) {
3090 bool IsNamedArg = ArgNo < NumRequiredArgs;
3092 if (IsRegCall && it->type->isStructureOrClassType())
3093 it->info = classifyRegCallStructType(it->type, NeededInt, NeededSSE,
3097 NeededSSE, IsNamedArg);
3103 if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
3104 FreeIntRegs -= NeededInt;
3105 FreeSSERegs -= NeededSSE;
3109 it->info = getIndirectResult(it->type, FreeIntRegs);
3118 llvm::Value *overflow_arg_area =
3133 llvm::Value *Res = overflow_arg_area;
3140 uint64_t SizeInBytes = (CGF.
getContext().getTypeSize(Ty) + 7) / 8;
3141 llvm::Value *Offset =
3142 llvm::ConstantInt::get(CGF.
Int32Ty, (SizeInBytes + 7) & ~7);
3144 Offset,
"overflow_arg_area.next");
3148 return Address(Res, LTy, Align);
3151RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
3152 QualType Ty, AggValueSlot Slot)
const {
3160 unsigned neededInt, neededSSE;
3172 if (!neededInt && !neededSSE)
3188 llvm::Value *InRegs =
nullptr;
3190 llvm::Value *gp_offset =
nullptr, *fp_offset =
nullptr;
3194 InRegs = llvm::ConstantInt::get(CGF.
Int32Ty, 48 - neededInt * 8);
3195 InRegs = CGF.
Builder.CreateICmpULE(gp_offset, InRegs,
"fits_in_gp");
3201 llvm::Value *FitsInFP =
3202 llvm::ConstantInt::get(CGF.
Int32Ty, 176 - neededSSE * 16);
3203 FitsInFP = CGF.
Builder.CreateICmpULE(fp_offset, FitsInFP,
"fits_in_fp");
3204 InRegs = InRegs ? CGF.
Builder.CreateAnd(InRegs, FitsInFP) : FitsInFP;
3210 CGF.
Builder.CreateCondBr(InRegs, InRegBlock, InMemBlock);
3231 if (neededInt && neededSSE) {
3233 assert(AI.
isDirect() &&
"Unexpected ABI info for mixed regs");
3237 assert(ST->getNumElements() == 2 &&
"Unexpected ABI info for mixed regs");
3238 llvm::Type *TyLo = ST->getElementType(0);
3239 llvm::Type *TyHi = ST->getElementType(1);
3240 assert((TyLo->isFPOrFPVectorTy() ^ TyHi->isFPOrFPVectorTy()) &&
3241 "Unexpected ABI info for mixed regs");
3242 llvm::Value *GPAddr =
3244 llvm::Value *FPAddr =
3246 llvm::Value *RegLoAddr = TyLo->isFPOrFPVectorTy() ? FPAddr : GPAddr;
3247 llvm::Value *RegHiAddr = TyLo->isFPOrFPVectorTy() ? GPAddr : FPAddr;
3263 }
else if (neededInt || neededSSE == 1) {
3265 auto TInfo = getContext().getTypeInfoInChars(Ty);
3266 uint64_t TySize = TInfo.Width.getQuantity();
3267 CharUnits TyAlign = TInfo.Align;
3268 llvm::Type *CoTy =
nullptr;
3272 llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset;
3273 uint64_t Alignment = neededInt ? 8 : 16;
3274 uint64_t RegSize = neededInt ? neededInt * 8 : 16;
3299 llvm::Value *PtrOffset =
3321 assert(neededSSE == 2 &&
"Invalid number of needed registers!");
3354 llvm::Value *Offset = llvm::ConstantInt::get(CGF.
Int32Ty, neededInt * 8);
3359 llvm::Value *Offset = llvm::ConstantInt::get(CGF.
Int32Ty, neededSSE * 16);
3378RValue X86_64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
3379 QualType Ty, AggValueSlot Slot)
const {
3382 uint64_t Width = getContext().getTypeSize(Ty);
3383 bool IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
3391ABIArgInfo WinX86_64ABIInfo::reclassifyHvaArgForVectorCall(
3392 QualType Ty,
unsigned &FreeSSERegs,
const ABIArgInfo ¤t)
const {
3397 isHomogeneousAggregate(Ty, Base, NumElts) && FreeSSERegs >= NumElts) {
3398 FreeSSERegs -= NumElts;
3399 return getDirectX86Hva();
3404ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty,
unsigned &FreeSSERegs,
3405 bool IsReturnType,
unsigned CC)
const {
3406 bool IsVectorCall = CC == llvm::CallingConv::X86_VectorCall;
3407 bool IsRegCall = CC == llvm::CallingConv::X86_RegCall;
3413 Ty = ED->getIntegerType();
3415 TypeInfo Info = getContext().getTypeInfo(Ty);
3417 CharUnits Align = getContext().toCharUnitsFromBits(Info.
Align);
3421 if (!IsReturnType) {
3423 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
3427 if (RT->getDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())
3428 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
3436 if ((IsVectorCall || IsRegCall) &&
3437 isHomogeneousAggregate(Ty, Base, NumElts)) {
3439 if (FreeSSERegs >= NumElts) {
3440 FreeSSERegs -= NumElts;
3446 Align, getDataLayout().getAllocaAddrSpace(),
3448 }
else if (IsVectorCall) {
3449 if (FreeSSERegs >= NumElts &&
3451 FreeSSERegs -= NumElts;
3453 }
else if (IsReturnType) {
3458 Align, getDataLayout().getAllocaAddrSpace(),
3467 llvm::Type *LLTy = CGT.ConvertType(Ty);
3468 if (LLTy->isPointerTy() || LLTy->isIntegerTy())
3475 if (Width > 64 || !llvm::isPowerOf2_64(Width))
3476 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
3483 if (
const BuiltinType *BT = Ty->
getAs<BuiltinType>()) {
3484 switch (BT->getKind()) {
3485 case BuiltinType::Bool:
3490 case BuiltinType::LongDouble:
3494 const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
3495 if (LDF == &llvm::APFloat::x87DoubleExtended())
3497 Align, getDataLayout().getAllocaAddrSpace(),
3502 case BuiltinType::Int128:
3503 case BuiltinType::UInt128:
3504 case BuiltinType::Float128:
3510 Align, getDataLayout().getAllocaAddrSpace(),
3515 if (BT->getKind() == BuiltinType::Int128 ||
3516 BT->getKind() == BuiltinType::UInt128)
3518 llvm::Type::getInt64Ty(getVMContext()), 2));
3522 if (BT->getKind() == BuiltinType::Float128) {
3523 auto IsWin64F128StackCC = [
this](
unsigned CC) ->
bool {
3525 case llvm::CallingConv::Win64:
3527 case llvm::CallingConv::C:
3528 return getTarget().getTriple().isOSWindowsOrUEFI();
3534 if (IsWin64F128StackCC(CC))
3535 return getNaturalAlignIndirect(
3536 Ty, getDataLayout().getAllocaAddrSpace(),
false);
3554 Align, getDataLayout().getAllocaAddrSpace(),
3561void WinX86_64ABIInfo::computeInfo(CGFunctionInfo &FI)
const {
3563 bool IsVectorCall = CC == llvm::CallingConv::X86_VectorCall;
3564 bool IsRegCall = CC == llvm::CallingConv::X86_RegCall;
3568 if (CC == llvm::CallingConv::X86_64_SysV) {
3569 X86_64ABIInfo SysVABIInfo(CGT, AVXLevel);
3570 SysVABIInfo.computeInfo(FI);
3574 unsigned FreeSSERegs = 0;
3578 }
else if (IsRegCall) {
3589 }
else if (IsRegCall) {
3594 unsigned ArgNum = 0;
3595 unsigned ZeroSSERegs = 0;
3600 unsigned *MaybeFreeSSERegs =
3601 (IsVectorCall && ArgNum >= 6) ? &ZeroSSERegs : &FreeSSERegs;
3602 I.
info = classify(I.
type, *MaybeFreeSSERegs,
false, CC);
3610 I.
info = reclassifyHvaArgForVectorCall(I.
type, FreeSSERegs, I.
info);
3614RValue WinX86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
3615 QualType Ty, AggValueSlot Slot)
const {
3618 uint64_t Width = getContext().getTypeSize(Ty);
3619 bool IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
3628 CodeGenModule &CGM,
bool DarwinVectorABI,
bool Win32StructABI,
3629 unsigned NumRegisterParameters,
bool SoftFloatABI) {
3630 bool RetSmallStructInRegABI = X86_32TargetCodeGenInfo::isStructReturnInRegABI(
3632 return std::make_unique<X86_32TargetCodeGenInfo>(
3633 CGM.
getTypes(), DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI,
3634 NumRegisterParameters, SoftFloatABI);
3638 CodeGenModule &CGM,
bool DarwinVectorABI,
bool Win32StructABI,
3639 unsigned NumRegisterParameters) {
3640 bool RetSmallStructInRegABI = X86_32TargetCodeGenInfo::isStructReturnInRegABI(
3642 return std::make_unique<WinX86_32TargetCodeGenInfo>(
3643 CGM.
getTypes(), DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI,
3644 NumRegisterParameters);
3647std::unique_ptr<TargetCodeGenInfo>
3650 return std::make_unique<X86_64TargetCodeGenInfo>(CGM.
getTypes(), AVXLevel);
3653std::unique_ptr<TargetCodeGenInfo>
3656 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 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.
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
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.
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 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.
@ 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