Changeset View
Standalone View
lib/CodeGen/TargetInfo.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 909 Lines • ▼ Show 20 Lines | ABIArgInfo PNaClABIInfo::classifyReturnType(QualType RetTy) const { | ||||
// Treat an enum type as its underlying type. | // Treat an enum type as its underlying type. | ||||
if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) | if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) | ||||
RetTy = EnumTy->getDecl()->getIntegerType(); | RetTy = EnumTy->getDecl()->getIntegerType(); | ||||
return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy) | return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend(RetTy) | ||||
: ABIArgInfo::getDirect()); | : ABIArgInfo::getDirect()); | ||||
} | } | ||||
/// IsX86_MMXType - Return true if this is an MMX type. | |||||
bool IsX86_MMXType(llvm::Type *IRType) { | |||||
rnk: I think looking at the LLVM type to decide how something should be passed is a bad pattern to… | |||||
For x86 32 bit target, no aggregate types end up getting passed in MMX register.
which is defined in header file (mmintrin.h): typedef long long __m64 __attribute__((__vector_size__(8), __aligned__(8))); Yes, it would be good if we define _m64 as a builtin type and handle it in AST level. But I'm afraid that it won't be a trivial work. Since GCC also handles __m64 in the same way as Clang currently does, can we just keep current implementation as it is? wxiao3: For x86 32 bit target, no aggregate types end up getting passed in MMX register.
The only type… | |||||
Not Done ReplyInline ActionsThat's not quite what I'm suggesting. I'm saying that IsX86_MMXType should take a QualType parameter, and it should check if that qualtype looks like the __m64 vector type, instead of converting the QualType to llvm::Type and then checking if the llvm::Type is a 64-bit vector. Does that seem reasonable? See the code near the call site conditionalized on IsDarwinVectorABI which already has similar logic. rnk: That's not quite what I'm suggesting. I'm saying that IsX86_MMXType should take a QualType… | |||||
Yes, it's unnecessary to convert QualType to llvm::Type just for the _m64 vector type checking. if (const VectorType *VT = RetTy->getAs<VectorType>()) I just remove the utility function: IsX86_MMXType. wxiao3: Yes, it's unnecessary to convert QualType to llvm::Type just for the _m64 vector type checking. | |||||
// Return true if the type is an MMX type <2 x i32>, <4 x i16>, or <8 x i8>. | |||||
return IRType->isVectorTy() && IRType->getPrimitiveSizeInBits() == 64 && | |||||
cast<llvm::VectorType>(IRType)->getElementType()->isIntegerTy() && | |||||
IRType->getScalarSizeInBits() != 64; | |||||
} | |||||
static llvm::Type* X86AdjustInlineAsmType(CodeGen::CodeGenFunction &CGF, | static llvm::Type* X86AdjustInlineAsmType(CodeGen::CodeGenFunction &CGF, | ||||
StringRef Constraint, | StringRef Constraint, | ||||
llvm::Type* Ty) { | llvm::Type* Ty) { | ||||
bool IsMMXCons = llvm::StringSwitch<bool>(Constraint) | bool IsMMXCons = llvm::StringSwitch<bool>(Constraint) | ||||
.Cases("y", "&y", "^Ym", true) | .Cases("y", "&y", "^Ym", true) | ||||
.Default(false); | .Default(false); | ||||
if (IsMMXCons && Ty->isVectorTy()) { | if (IsMMXCons && Ty->isVectorTy()) { | ||||
if (cast<llvm::VectorType>(Ty)->getBitWidth() != 64) { | if (cast<llvm::VectorType>(Ty)->getBitWidth() != 64) { | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | class X86_32ABIInfo : public SwiftABIInfo { | ||||
static const unsigned MinABIStackAlignInBytes = 4; | static const unsigned MinABIStackAlignInBytes = 4; | ||||
bool IsDarwinVectorABI; | bool IsDarwinVectorABI; | ||||
bool IsRetSmallStructInRegABI; | bool IsRetSmallStructInRegABI; | ||||
bool IsWin32StructABI; | bool IsWin32StructABI; | ||||
bool IsSoftFloatABI; | bool IsSoftFloatABI; | ||||
bool IsMCUABI; | bool IsMCUABI; | ||||
bool IsLinuxABI; | |||||
mgornyUnsubmitted Not Done ReplyInline ActionsMaybe replace the two booleans with something alike IsPassInMMXRegABI? And while at it, include NetBSD there, please. mgorny: Maybe replace the two booleans with something alike `IsPassInMMXRegABI`? And while at it… | |||||
rjmccallUnsubmitted Not Done ReplyInline ActionsCGT is a member variable, so you can just query the target fresh in your isPassInMMXRegABI method. The check upfront for a 64-bit vector type should keep this well out of the fast path. rjmccall: `CGT` is a member variable, so you can just query the target fresh in your `isPassInMMXRegABI`… | |||||
unsigned DefaultNumRegisterParameters; | unsigned DefaultNumRegisterParameters; | ||||
bool IsMMXEnabled; | |||||
static bool isRegisterSize(unsigned Size) { | static bool isRegisterSize(unsigned Size) { | ||||
return (Size == 8 || Size == 16 || Size == 32 || Size == 64); | return (Size == 8 || Size == 16 || Size == 32 || Size == 64); | ||||
} | } | ||||
bool isHomogeneousAggregateBaseType(QualType Ty) const override { | bool isHomogeneousAggregateBaseType(QualType Ty) const override { | ||||
// FIXME: Assumes vectorcall is in use. | // FIXME: Assumes vectorcall is in use. | ||||
return isX86VectorTypeForVectorCall(getContext(), Ty); | return isX86VectorTypeForVectorCall(getContext(), Ty); | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
public: | public: | ||||
void computeInfo(CGFunctionInfo &FI) const override; | void computeInfo(CGFunctionInfo &FI) const override; | ||||
Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, | Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, | ||||
QualType Ty) const override; | QualType Ty) const override; | ||||
X86_32ABIInfo(CodeGen::CodeGenTypes &CGT, bool DarwinVectorABI, | X86_32ABIInfo(CodeGen::CodeGenTypes &CGT, bool DarwinVectorABI, | ||||
bool RetSmallStructInRegABI, bool Win32StructABI, | bool RetSmallStructInRegABI, bool Win32StructABI, | ||||
unsigned NumRegisterParameters, bool SoftFloatABI) | unsigned NumRegisterParameters, bool SoftFloatABI, | ||||
bool MMXEnabled) | |||||
: SwiftABIInfo(CGT), IsDarwinVectorABI(DarwinVectorABI), | : SwiftABIInfo(CGT), IsDarwinVectorABI(DarwinVectorABI), | ||||
IsRetSmallStructInRegABI(RetSmallStructInRegABI), | IsRetSmallStructInRegABI(RetSmallStructInRegABI), | ||||
IsWin32StructABI(Win32StructABI), | IsWin32StructABI(Win32StructABI), | ||||
IsSoftFloatABI(SoftFloatABI), | IsSoftFloatABI(SoftFloatABI), | ||||
IsMCUABI(CGT.getTarget().getTriple().isOSIAMCU()), | IsMCUABI(CGT.getTarget().getTriple().isOSIAMCU()), | ||||
DefaultNumRegisterParameters(NumRegisterParameters) {} | IsLinuxABI(CGT.getTarget().getTriple().isOSLinux()), | ||||
DefaultNumRegisterParameters(NumRegisterParameters), | |||||
IsMMXEnabled(MMXEnabled) {} | |||||
bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars, | bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars, | ||||
bool asReturnValue) const override { | bool asReturnValue) const override { | ||||
// LLVM's x86-32 lowering currently only assigns up to three | // LLVM's x86-32 lowering currently only assigns up to three | ||||
// integer registers and three fp registers. Oddly, it'll use up to | // integer registers and three fp registers. Oddly, it'll use up to | ||||
// four vector registers for vectors, but those can overlap with the | // four vector registers for vectors, but those can overlap with the | ||||
// scalar registers. | // scalar registers. | ||||
return occupiesMoreThan(CGT, scalars, /*total*/ 3); | return occupiesMoreThan(CGT, scalars, /*total*/ 3); | ||||
} | } | ||||
bool isSwiftErrorInRegister() const override { | bool isSwiftErrorInRegister() const override { | ||||
// x86-32 lowering does not support passing swifterror in a register. | // x86-32 lowering does not support passing swifterror in a register. | ||||
return false; | return false; | ||||
} | } | ||||
}; | }; | ||||
class X86_32TargetCodeGenInfo : public TargetCodeGenInfo { | class X86_32TargetCodeGenInfo : public TargetCodeGenInfo { | ||||
public: | public: | ||||
X86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool DarwinVectorABI, | X86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool DarwinVectorABI, | ||||
bool RetSmallStructInRegABI, bool Win32StructABI, | bool RetSmallStructInRegABI, bool Win32StructABI, | ||||
Not Done ReplyInline Actions"The System V i386 psABI requires __m64 to be passed in MMX registers. rjmccall: "The System V i386 psABI requires __m64 to be passed in MMX registers.
Clang historically had a… | |||||
unsigned NumRegisterParameters, bool SoftFloatABI) | unsigned NumRegisterParameters, bool SoftFloatABI, | ||||
bool MMXEnabled = false) | |||||
: TargetCodeGenInfo(new X86_32ABIInfo( | : TargetCodeGenInfo(new X86_32ABIInfo( | ||||
CGT, DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI, | CGT, DarwinVectorABI, RetSmallStructInRegABI, Win32StructABI, | ||||
NumRegisterParameters, SoftFloatABI)) {} | NumRegisterParameters, SoftFloatABI, MMXEnabled)) {} | ||||
static bool isStructReturnInRegABI( | static bool isStructReturnInRegABI( | ||||
const llvm::Triple &Triple, const CodeGenOptions &Opts); | const llvm::Triple &Triple, const CodeGenOptions &Opts); | ||||
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, | void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, | ||||
CodeGen::CodeGenModule &CGM) const override; | CodeGen::CodeGenModule &CGM) const override; | ||||
int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override { | int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override { | ||||
▲ Show 20 Lines • Show All 269 Lines • ▼ Show 20 Lines | ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, | ||||
if ((State.CC == llvm::CallingConv::X86_VectorCall || | if ((State.CC == llvm::CallingConv::X86_VectorCall || | ||||
State.CC == llvm::CallingConv::X86_RegCall) && | State.CC == llvm::CallingConv::X86_RegCall) && | ||||
isHomogeneousAggregate(RetTy, Base, NumElts)) { | isHomogeneousAggregate(RetTy, Base, NumElts)) { | ||||
// The LLVM struct type for such an aggregate should lower properly. | // The LLVM struct type for such an aggregate should lower properly. | ||||
return ABIArgInfo::getDirect(); | return ABIArgInfo::getDirect(); | ||||
} | } | ||||
if (const VectorType *VT = RetTy->getAs<VectorType>()) { | if (const VectorType *VT = RetTy->getAs<VectorType>()) { | ||||
uint64_t Size = getContext().getTypeSize(RetTy); | |||||
// On Darwin, some vectors are returned in registers. | // On Darwin, some vectors are returned in registers. | ||||
if (IsDarwinVectorABI) { | if (IsDarwinVectorABI) { | ||||
uint64_t Size = getContext().getTypeSize(RetTy); | |||||
// 128-bit vectors are a special case; they are returned in | // 128-bit vectors are a special case; they are returned in | ||||
// registers and we need to make sure to pick a type the LLVM | // registers and we need to make sure to pick a type the LLVM | ||||
// backend will like. | // backend will like. | ||||
if (Size == 128) | if (Size == 128) | ||||
return ABIArgInfo::getDirect(llvm::VectorType::get( | return ABIArgInfo::getDirect(llvm::VectorType::get( | ||||
llvm::Type::getInt64Ty(getVMContext()), 2)); | llvm::Type::getInt64Ty(getVMContext()), 2)); | ||||
// Always return in register if it fits in a general purpose | // Always return in register if it fits in a general purpose | ||||
// register, or if it is 64 bits and has a single element. | // register, or if it is 64 bits and has a single element. | ||||
if ((Size == 8 || Size == 16 || Size == 32) || | if ((Size == 8 || Size == 16 || Size == 32) || | ||||
(Size == 64 && VT->getNumElements() == 1)) | (Size == 64 && VT->getNumElements() == 1)) | ||||
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), | return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), | ||||
Size)); | Size)); | ||||
return getIndirectReturnResult(RetTy, State); | return getIndirectReturnResult(RetTy, State); | ||||
} | } | ||||
if (VT->getElementType()->isIntegerType() && Size == 64 && IsMMXEnabled && | |||||
IsLinuxABI) | |||||
Not Done ReplyInline ActionsIndentation on the continuation line. rjmccall: Indentation on the continuation line. | |||||
return ABIArgInfo::getDirect(llvm::Type::getX86_MMXTy(getVMContext())); | |||||
superfluous braces? RKSimon: superfluous braces? | |||||
return ABIArgInfo::getDirect(); | return ABIArgInfo::getDirect(); | ||||
} | } | ||||
if (isAggregateTypeForABI(RetTy)) { | if (isAggregateTypeForABI(RetTy)) { | ||||
if (const RecordType *RT = RetTy->getAs<RecordType>()) { | if (const RecordType *RT = RetTy->getAs<RecordType>()) { | ||||
// Structures with flexible arrays are always indirect. | // Structures with flexible arrays are always indirect. | ||||
if (RT->getDecl()->hasFlexibleArrayMember()) | if (RT->getDecl()->hasFlexibleArrayMember()) | ||||
return getIndirectReturnResult(RetTy, State); | return getIndirectReturnResult(RetTy, State); | ||||
▲ Show 20 Lines • Show All 278 Lines • ▼ Show 20 Lines | if (getContext().getTypeSize(Ty) <= 4 * 32 && | ||||
State.CC == llvm::CallingConv::X86_VectorCall || | State.CC == llvm::CallingConv::X86_VectorCall || | ||||
State.CC == llvm::CallingConv::X86_RegCall, | State.CC == llvm::CallingConv::X86_RegCall, | ||||
PaddingType); | PaddingType); | ||||
return getIndirectResult(Ty, true, State); | return getIndirectResult(Ty, true, State); | ||||
} | } | ||||
if (const VectorType *VT = Ty->getAs<VectorType>()) { | if (const VectorType *VT = Ty->getAs<VectorType>()) { | ||||
uint64_t Size = getContext().getTypeSize(Ty); | |||||
// On Darwin, some vectors are passed in memory, we handle this by passing | // On Darwin, some vectors are passed in memory, we handle this by passing | ||||
// it as an i8/i16/i32/i64. | // it as an i8/i16/i32/i64. | ||||
if (IsDarwinVectorABI) { | if (IsDarwinVectorABI) { | ||||
uint64_t Size = getContext().getTypeSize(Ty); | |||||
if ((Size == 8 || Size == 16 || Size == 32) || | if ((Size == 8 || Size == 16 || Size == 32) || | ||||
(Size == 64 && VT->getNumElements() == 1)) | (Size == 64 && VT->getNumElements() == 1)) | ||||
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), | return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), | ||||
Size)); | Size)); | ||||
} | } | ||||
if (IsX86_MMXType(CGT.ConvertType(Ty))) | if (VT->getElementType()->isIntegerType() && Size == 64) { | ||||
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), 64)); | // System V i386 ABI requires __m64 value pass by MMX registers. | ||||
// Apply it to Linux only since other Systems (e.g Darwin, PS4, FreeBSD | |||||
// and NetBSD) don't want to spend any effort dealing with the | |||||
// ramifications of ABI breaks at present. | |||||
if (IsMMXEnabled && IsLinuxABI) | |||||
return ABIArgInfo::getDirect(llvm::Type::getX86_MMXTy(getVMContext())); | |||||
else | |||||
return ABIArgInfo::getDirect( | |||||
llvm::IntegerType::get(getVMContext(), 64)); | |||||
} | |||||
return ABIArgInfo::getDirect(); | return ABIArgInfo::getDirect(); | ||||
} | } | ||||
if (const EnumType *EnumTy = Ty->getAs<EnumType>()) | if (const EnumType *EnumTy = Ty->getAs<EnumType>()) | ||||
Ty = EnumTy->getDecl()->getIntegerType(); | Ty = EnumTy->getDecl()->getIntegerType(); | ||||
bool InReg = shouldPrimitiveUseInReg(Ty, State); | bool InReg = shouldPrimitiveUseInReg(Ty, State); | ||||
if (Ty->isPromotableIntegerType()) { | if (Ty->isPromotableIntegerType()) { | ||||
if (InReg) | if (InReg) | ||||
return ABIArgInfo::getExtendInReg(Ty); | return ABIArgInfo::getExtendInReg(Ty); | ||||
▲ Show 20 Lines • Show All 7,725 Lines • ▼ Show 20 Lines | case llvm::Triple::x86: { | ||||
bool RetSmallStructInRegABI = | bool RetSmallStructInRegABI = | ||||
X86_32TargetCodeGenInfo::isStructReturnInRegABI(Triple, CodeGenOpts); | X86_32TargetCodeGenInfo::isStructReturnInRegABI(Triple, CodeGenOpts); | ||||
bool IsWin32FloatStructABI = Triple.isOSWindows() && !Triple.isOSCygMing(); | bool IsWin32FloatStructABI = Triple.isOSWindows() && !Triple.isOSCygMing(); | ||||
if (Triple.getOS() == llvm::Triple::Win32) { | if (Triple.getOS() == llvm::Triple::Win32) { | ||||
return SetCGInfo(new WinX86_32TargetCodeGenInfo( | return SetCGInfo(new WinX86_32TargetCodeGenInfo( | ||||
Types, IsDarwinVectorABI, RetSmallStructInRegABI, | Types, IsDarwinVectorABI, RetSmallStructInRegABI, | ||||
IsWin32FloatStructABI, CodeGenOpts.NumRegisterParameters)); | IsWin32FloatStructABI, CodeGenOpts.NumRegisterParameters)); | ||||
} else { | } else { | ||||
bool EnableMMX = getContext().getTargetInfo().getABI() != "no-mmx"; | |||||
The Sys V rules apply to every non-Windows OS, not just Linux. I think you should add the parameter regardless of the OS rnk: The Sys V rules apply to every non-Windows OS, not just Linux. I think you should add the… | |||||
return SetCGInfo(new X86_32TargetCodeGenInfo( | return SetCGInfo(new X86_32TargetCodeGenInfo( | ||||
Not Done ReplyInline ActionsI think this needs to preserve existing behavior for Darwin and PS4 based on comments from @rjmccall and @dexonsmith in D60748. rnk: I think this needs to preserve existing behavior for Darwin and PS4 based on comments from… | |||||
ok, I will follow it. wxiao3: ok, I will follow it. | |||||
Types, IsDarwinVectorABI, RetSmallStructInRegABI, | Types, IsDarwinVectorABI, RetSmallStructInRegABI, | ||||
IsWin32FloatStructABI, CodeGenOpts.NumRegisterParameters, | IsWin32FloatStructABI, CodeGenOpts.NumRegisterParameters, | ||||
CodeGenOpts.FloatABI == "soft")); | CodeGenOpts.FloatABI == "soft", EnableMMX)); | ||||
} | } | ||||
} | } | ||||
case llvm::Triple::x86_64: { | case llvm::Triple::x86_64: { | ||||
StringRef ABI = getTarget().getABI(); | StringRef ABI = getTarget().getABI(); | ||||
X86AVXABILevel AVXLevel = | X86AVXABILevel AVXLevel = | ||||
(ABI == "avx512" | (ABI == "avx512" | ||||
? X86AVXABILevel::AVX512 | ? X86AVXABILevel::AVX512 | ||||
▲ Show 20 Lines • Show All 135 Lines • Show Last 20 Lines |
I think looking at the LLVM type to decide how something should be passed is a bad pattern to follow. We should look at the clang AST to decide how things will be passed, not LLVM types. Would that be complicated? Are there aggregate types that end up getting passed directly in MMX registers?