diff options
Diffstat (limited to 'lib/CodeGen/TargetInfo.cpp')
-rw-r--r-- | lib/CodeGen/TargetInfo.cpp | 420 |
1 files changed, 347 insertions, 73 deletions
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index df2c1bd98cca..e1dc8f7ffdbd 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -57,12 +57,12 @@ const llvm::TargetData &ABIInfo::getTargetData() const { void ABIArgInfo::dump() const { - llvm::raw_ostream &OS = llvm::errs(); + raw_ostream &OS = llvm::errs(); OS << "(ABIArgInfo Kind="; switch (TheKind) { case Direct: OS << "Direct Type="; - if (const llvm::Type *Ty = getCoerceToType()) + if (llvm::Type *Ty = getCoerceToType()) Ty->print(OS); else OS << "null"; @@ -87,6 +87,25 @@ void ABIArgInfo::dump() const { TargetCodeGenInfo::~TargetCodeGenInfo() { delete Info; } +// If someone can figure out a general rule for this, that would be great. +// It's probably just doomed to be platform-dependent, though. +unsigned TargetCodeGenInfo::getSizeOfUnwindException() const { + // Verified for: + // x86-64 FreeBSD, Linux, Darwin + // x86-32 FreeBSD, Linux, Darwin + // PowerPC Linux, Darwin + // ARM Darwin (*not* EABI) + return 32; +} + +bool TargetCodeGenInfo::isNoProtoCallVariadic(CallingConv CC) const { + // The following conventions are known to require this to be false: + // x86_stdcall + // MIPS + // For everything else, we just prefer false unless we opt out. + return false; +} + static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays); /// isEmptyField - Return true iff a the field is "empty", that is it @@ -348,7 +367,7 @@ ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const { /// UseX86_MMXType - Return true if this is an MMX type that should use the special /// x86_mmx type. -bool UseX86_MMXType(const llvm::Type *IRType) { +bool UseX86_MMXType(llvm::Type *IRType) { // If the type is an MMX type <2 x i32>, <4 x i16>, or <8 x i8>, use the // special x86_mmx type. return IRType->isVectorTy() && IRType->getPrimitiveSizeInBits() == 64 && @@ -357,7 +376,7 @@ bool UseX86_MMXType(const llvm::Type *IRType) { } static llvm::Type* X86AdjustInlineAsmType(CodeGen::CodeGenFunction &CGF, - llvm::StringRef Constraint, + StringRef Constraint, llvm::Type* Ty) { if ((Constraint == "y" || Constraint == "&y") && Ty->isVectorTy()) return llvm::Type::getX86_MMXTy(CGF.getLLVMContext()); @@ -428,7 +447,7 @@ public: llvm::Value *Address) const; llvm::Type* adjustInlineAsmType(CodeGen::CodeGenFunction &CGF, - llvm::StringRef Constraint, + StringRef Constraint, llvm::Type* Ty) const { return X86AdjustInlineAsmType(CGF, Constraint, Ty); } @@ -724,8 +743,8 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty) const { llvm::Value *X86_32ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const { - const llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); - const llvm::Type *BPP = llvm::PointerType::getUnqual(BP); + llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); + llvm::Type *BPP = llvm::PointerType::getUnqual(BP); CGBuilderTy &Builder = CGF.Builder; llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, @@ -765,7 +784,7 @@ bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable( CodeGen::CGBuilderTy &Builder = CGF.Builder; llvm::LLVMContext &Context = CGF.getLLVMContext(); - const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); + llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4); // 0-7 are the eight integer registers; the order is different @@ -892,7 +911,7 @@ class X86_64ABIInfo : public ABIInfo { /// required strict binary compatibility with older versions of GCC /// may need to exempt themselves. bool honorsRevision0_98() const { - return !getContext().Target.getTriple().isOSDarwin(); + return !getContext().getTargetInfo().getTriple().isOSDarwin(); } public: @@ -932,7 +951,7 @@ public: CodeGen::CGBuilderTy &Builder = CGF.Builder; llvm::LLVMContext &Context = CGF.getLLVMContext(); - const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); + llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8); // 0-15 are the 16 integer registers. @@ -943,11 +962,20 @@ public: } llvm::Type* adjustInlineAsmType(CodeGen::CodeGenFunction &CGF, - llvm::StringRef Constraint, + StringRef Constraint, llvm::Type* Ty) const { return X86AdjustInlineAsmType(CGF, Constraint, Ty); } + bool isNoProtoCallVariadic(CallingConv CC) const { + // The default CC on x86-64 sets %al to the number of SSA + // registers used, and GCC sets this when calling an unprototyped + // function, so we override the default behavior. + if (CC == CC_Default || CC == CC_C) return true; + + return TargetCodeGenInfo::isNoProtoCallVariadic(CC); + } + }; class WinX86_64TargetCodeGenInfo : public TargetCodeGenInfo { @@ -964,7 +992,7 @@ public: CodeGen::CGBuilderTy &Builder = CGF.Builder; llvm::LLVMContext &Context = CGF.getLLVMContext(); - const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); + llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8); // 0-15 are the 16 integer registers. @@ -1309,8 +1337,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, continue; uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx); - uint64_t Size = - i->getBitWidth()->EvaluateAsInt(getContext()).getZExtValue(); + uint64_t Size = i->getBitWidthValue(getContext()); uint64_t EB_Lo = Offset / 64; uint64_t EB_Hi = (Offset + Size - 1) / 64; @@ -1489,14 +1516,14 @@ static bool BitsContainNoUserData(QualType Ty, unsigned StartBit, /// float member at the specified offset. For example, {int,{float}} has a /// float at offset 4. It is conservatively correct for this routine to return /// false. -static bool ContainsFloatAtOffset(const llvm::Type *IRType, unsigned IROffset, +static bool ContainsFloatAtOffset(llvm::Type *IRType, unsigned IROffset, const llvm::TargetData &TD) { // Base case if we find a float. if (IROffset == 0 && IRType->isFloatTy()) return true; // If this is a struct, recurse into the field at the specified offset. - if (const llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) { + if (llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) { const llvm::StructLayout *SL = TD.getStructLayout(STy); unsigned Elt = SL->getElementContainingOffset(IROffset); IROffset -= SL->getElementOffset(Elt); @@ -1504,8 +1531,8 @@ static bool ContainsFloatAtOffset(const llvm::Type *IRType, unsigned IROffset, } // If this is an array, recurse into the field at the specified offset. - if (const llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) { - const llvm::Type *EltTy = ATy->getElementType(); + if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) { + llvm::Type *EltTy = ATy->getElementType(); unsigned EltSize = TD.getTypeAllocSize(EltTy); IROffset -= IROffset/EltSize*EltSize; return ContainsFloatAtOffset(EltTy, IROffset, TD); @@ -1578,7 +1605,7 @@ GetINTEGERTypeAtOffset(llvm::Type *IRType, unsigned IROffset, } } - if (const llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) { + if (llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) { // If this is a struct, recurse into the field at the specified offset. const llvm::StructLayout *SL = getTargetData().getStructLayout(STy); if (IROffset < SL->getSizeInBytes()) { @@ -1590,7 +1617,7 @@ GetINTEGERTypeAtOffset(llvm::Type *IRType, unsigned IROffset, } } - if (const llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) { + if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) { llvm::Type *EltTy = ATy->getElementType(); unsigned EltSize = getTargetData().getTypeAllocSize(EltTy); unsigned EltOffset = IROffset/EltSize*EltSize; @@ -1678,7 +1705,7 @@ classifyReturnType(QualType RetTy) const { case SSEUp: case X87Up: - assert(0 && "Invalid classification for lo word."); + llvm_unreachable("Invalid classification for lo word."); // AMD64-ABI 3.2.3p4: Rule 2. Types of class memory are returned via // hidden argument. @@ -1732,7 +1759,7 @@ classifyReturnType(QualType RetTy) const { // never occur as a hi class. case Memory: case X87: - assert(0 && "Invalid classification for hi word."); + llvm_unreachable("Invalid classification for hi word."); case ComplexX87: // Previously handled. case NoClass: @@ -1820,7 +1847,7 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned &neededInt, case SSEUp: case X87Up: - assert(0 && "Invalid classification for lo word."); + llvm_unreachable("Invalid classification for lo word."); // AMD64-ABI 3.2.3p3: Rule 2. If the class is INTEGER, the next // available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8 @@ -1864,8 +1891,7 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned &neededInt, case Memory: case X87: case ComplexX87: - assert(0 && "Invalid classification for hi word."); - break; + llvm_unreachable("Invalid classification for hi word."); case NoClass: break; @@ -1970,7 +1996,7 @@ static llvm::Value *EmitVAArgFromMemory(llvm::Value *VAListAddr, } // AMD64-ABI 3.5.7p5: Step 8. Fetch type from l->overflow_arg_area. - const llvm::Type *LTy = CGF.ConvertTypeForMem(Ty); + llvm::Type *LTy = CGF.ConvertTypeForMem(Ty); llvm::Value *Res = CGF.Builder.CreateBitCast(overflow_arg_area, llvm::PointerType::getUnqual(LTy)); @@ -2061,22 +2087,22 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, // collect arguments from different places; often what should result in a // simple assembling of a structure from scattered addresses has many more // loads than necessary. Can we clean this up? - const llvm::Type *LTy = CGF.ConvertTypeForMem(Ty); + llvm::Type *LTy = CGF.ConvertTypeForMem(Ty); llvm::Value *RegAddr = CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(VAListAddr, 3), "reg_save_area"); if (neededInt && neededSSE) { // FIXME: Cleanup. assert(AI.isDirect() && "Unexpected ABI info for mixed regs"); - const llvm::StructType *ST = cast<llvm::StructType>(AI.getCoerceToType()); + llvm::StructType *ST = cast<llvm::StructType>(AI.getCoerceToType()); llvm::Value *Tmp = CGF.CreateTempAlloca(ST); assert(ST->getNumElements() == 2 && "Unexpected ABI info for mixed regs"); - const llvm::Type *TyLo = ST->getElementType(0); - const llvm::Type *TyHi = ST->getElementType(1); + llvm::Type *TyLo = ST->getElementType(0); + llvm::Type *TyHi = ST->getElementType(1); assert((TyLo->isFPOrFPVectorTy() ^ TyHi->isFPOrFPVectorTy()) && "Unexpected ABI info for mixed regs"); - const llvm::Type *PTyLo = llvm::PointerType::getUnqual(TyLo); - const llvm::Type *PTyHi = llvm::PointerType::getUnqual(TyHi); + llvm::Type *PTyLo = llvm::PointerType::getUnqual(TyLo); + llvm::Type *PTyHi = llvm::PointerType::getUnqual(TyHi); llvm::Value *GPAddr = CGF.Builder.CreateGEP(RegAddr, gp_offset); llvm::Value *FPAddr = CGF.Builder.CreateGEP(RegAddr, fp_offset); llvm::Value *RegLoAddr = TyLo->isFloatingPointTy() ? FPAddr : GPAddr; @@ -2104,9 +2130,9 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, llvm::Value *RegAddrLo = CGF.Builder.CreateGEP(RegAddr, fp_offset); llvm::Value *RegAddrHi = CGF.Builder.CreateConstGEP1_32(RegAddrLo, 16); llvm::Type *DoubleTy = llvm::Type::getDoubleTy(VMContext); - const llvm::Type *DblPtrTy = + llvm::Type *DblPtrTy = llvm::PointerType::getUnqual(DoubleTy); - const llvm::StructType *ST = llvm::StructType::get(DoubleTy, + llvm::StructType *ST = llvm::StructType::get(DoubleTy, DoubleTy, NULL); llvm::Value *V, *Tmp = CGF.CreateTempAlloca(ST); V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegAddrLo, @@ -2166,7 +2192,7 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty) const { // FIXME: mingw-w64-gcc emits 128-bit struct as i128 if (Size == 128 && - getContext().Target.getTriple().getOS() == llvm::Triple::MinGW32) + getContext().getTargetInfo().getTriple().getOS() == llvm::Triple::MinGW32) return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size)); @@ -2198,8 +2224,8 @@ void WinX86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const { llvm::Value *WinX86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const { - const llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); - const llvm::Type *BPP = llvm::PointerType::getUnqual(BP); + llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); + llvm::Type *BPP = llvm::PointerType::getUnqual(BP); CGBuilderTy &Builder = CGF.Builder; llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, @@ -2246,7 +2272,7 @@ PPC32TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, CodeGen::CGBuilderTy &Builder = CGF.Builder; llvm::LLVMContext &Context = CGF.getLLVMContext(); - const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); + llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4); llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8); llvm::Value *Sixteen8 = llvm::ConstantInt::get(i8, 16); @@ -2300,6 +2326,11 @@ private: public: ARMABIInfo(CodeGenTypes &CGT, ABIKind _Kind) : ABIInfo(CGT), Kind(_Kind) {} + bool isEABI() const { + StringRef Env = getContext().getTargetInfo().getTriple().getEnvironmentName(); + return (Env == "gnueabi" || Env == "eabi"); + } + private: ABIKind getABIKind() const { return Kind; } @@ -2317,11 +2348,15 @@ public: ARMTargetCodeGenInfo(CodeGenTypes &CGT, ARMABIInfo::ABIKind K) :TargetCodeGenInfo(new ARMABIInfo(CGT, K)) {} + const ARMABIInfo &getABIInfo() const { + return static_cast<const ARMABIInfo&>(TargetCodeGenInfo::getABIInfo()); + } + int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const { return 13; } - llvm::StringRef getARCRetainAutoreleasedReturnValueMarker() const { + StringRef getARCRetainAutoreleasedReturnValueMarker() const { return "mov\tr7, r7\t\t@ marker for objc_retainAutoreleaseReturnValue"; } @@ -2330,7 +2365,7 @@ public: CodeGen::CGBuilderTy &Builder = CGF.Builder; llvm::LLVMContext &Context = CGF.getLLVMContext(); - const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); + llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4); // 0-15 are the 16 integer registers. @@ -2338,6 +2373,11 @@ public: return false; } + + unsigned getSizeOfUnwindException() const { + if (getABIInfo().isEABI()) return 88; + return TargetCodeGenInfo::getSizeOfUnwindException(); + } }; } @@ -2354,8 +2394,7 @@ void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const { // Calling convention as default by an ABI. llvm::CallingConv::ID DefaultCC; - llvm::StringRef Env = getContext().Target.getTriple().getEnvironmentName(); - if (Env == "gnueabi" || Env == "eabi") + if (isEABI()) DefaultCC = llvm::CallingConv::ARM_AAPCS; else DefaultCC = llvm::CallingConv::ARM_APCS; @@ -2379,6 +2418,73 @@ void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const { } } +/// isHomogeneousAggregate - Return true if a type is an AAPCS-VFP homogeneous +/// aggregate. If HAMembers is non-null, the number of base elements +/// contained in the type is returned through it; this is used for the +/// recursive calls that check aggregate component types. +static bool isHomogeneousAggregate(QualType Ty, const Type *&Base, + ASTContext &Context, + uint64_t *HAMembers = 0) { + uint64_t Members; + if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) { + if (!isHomogeneousAggregate(AT->getElementType(), Base, Context, &Members)) + return false; + Members *= AT->getSize().getZExtValue(); + } else if (const RecordType *RT = Ty->getAs<RecordType>()) { + const RecordDecl *RD = RT->getDecl(); + if (RD->isUnion() || RD->hasFlexibleArrayMember()) + return false; + if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { + if (!CXXRD->isAggregate()) + return false; + } + Members = 0; + for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); + i != e; ++i) { + const FieldDecl *FD = *i; + uint64_t FldMembers; + if (!isHomogeneousAggregate(FD->getType(), Base, Context, &FldMembers)) + return false; + Members += FldMembers; + } + } else { + Members = 1; + if (const ComplexType *CT = Ty->getAs<ComplexType>()) { + Members = 2; + Ty = CT->getElementType(); + } + + // Homogeneous aggregates for AAPCS-VFP must have base types of float, + // double, or 64-bit or 128-bit vectors. + if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) { + if (BT->getKind() != BuiltinType::Float && + BT->getKind() != BuiltinType::Double) + return false; + } else if (const VectorType *VT = Ty->getAs<VectorType>()) { + unsigned VecSize = Context.getTypeSize(VT); + if (VecSize != 64 && VecSize != 128) + return false; + } else { + return false; + } + + // The base type must be the same for all members. Vector types of the + // same total size are treated as being equivalent here. + const Type *TyPtr = Ty.getTypePtr(); + if (!Base) + Base = TyPtr; + if (Base != TyPtr && + (!Base->isVectorType() || !TyPtr->isVectorType() || + Context.getTypeSize(Base) != Context.getTypeSize(TyPtr))) + return false; + } + + // Homogeneous Aggregates can have at most 4 members of the base type. + if (HAMembers) + *HAMembers = Members; + return (Members <= 4); +} + ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty) const { if (!isAggregateTypeForABI(Ty)) { // Treat an enum type as its underlying type. @@ -2398,23 +2504,26 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty) const { if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty)) return ABIArgInfo::getIndirect(0, /*ByVal=*/false); + if (getABIKind() == ARMABIInfo::AAPCS_VFP) { + // Homogeneous Aggregates need to be expanded. + const Type *Base = 0; + if (isHomogeneousAggregate(Ty, Base, getContext())) + return ABIArgInfo::getExpand(); + } + // Otherwise, pass by coercing to a structure of the appropriate size. // + // FIXME: This is kind of nasty... but there isn't much choice because the ARM + // backend doesn't support byval. // FIXME: This doesn't handle alignment > 64 bits. - const llvm::Type* ElemTy; + llvm::Type* ElemTy; unsigned SizeRegs; - if (getContext().getTypeSizeInChars(Ty) <= CharUnits::fromQuantity(64)) { - ElemTy = llvm::Type::getInt32Ty(getVMContext()); - SizeRegs = (getContext().getTypeSize(Ty) + 31) / 32; - } else if (getABIKind() == ARMABIInfo::APCS) { - // Initial ARM ByVal support is APCS-only. - return ABIArgInfo::getIndirect(0, /*ByVal=*/true); - } else { - // FIXME: This is kind of nasty... but there isn't much choice - // because most of the ARM calling conventions don't yet support - // byval. + if (getContext().getTypeAlign(Ty) > 32) { ElemTy = llvm::Type::getInt64Ty(getVMContext()); SizeRegs = (getContext().getTypeSize(Ty) + 63) / 64; + } else { + ElemTy = llvm::Type::getInt32Ty(getVMContext()); + SizeRegs = (getContext().getTypeSize(Ty) + 31) / 32; } llvm::Type *STy = @@ -2579,14 +2688,23 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy) const { llvm::Value *ARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const { - // FIXME: Need to handle alignment - const llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); - const llvm::Type *BPP = llvm::PointerType::getUnqual(BP); + llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); + llvm::Type *BPP = llvm::PointerType::getUnqual(BP); CGBuilderTy &Builder = CGF.Builder; llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap"); llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur"); + // Handle address alignment for type alignment > 32 bits + uint64_t TyAlign = CGF.getContext().getTypeAlign(Ty) / 8; + if (TyAlign > 4) { + assert((TyAlign & (TyAlign - 1)) == 0 && + "Alignment is not power of 2!"); + llvm::Value *AddrAsInt = Builder.CreatePtrToInt(Addr, CGF.Int32Ty); + AddrAsInt = Builder.CreateAdd(AddrAsInt, Builder.getInt32(TyAlign - 1)); + AddrAsInt = Builder.CreateAnd(AddrAsInt, Builder.getInt32(~(TyAlign - 1))); + Addr = Builder.CreateIntToPtr(AddrAsInt, BP); + } llvm::Type *PTy = llvm::PointerType::getUnqual(CGF.ConvertType(Ty)); llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy); @@ -2623,6 +2741,9 @@ class PTXTargetCodeGenInfo : public TargetCodeGenInfo { public: PTXTargetCodeGenInfo(CodeGenTypes &CGT) : TargetCodeGenInfo(new PTXABIInfo(CGT)) {} + + virtual void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV, + CodeGen::CodeGenModule &M) const; }; ABIArgInfo PTXABIInfo::classifyReturnType(QualType RetTy) const { @@ -2652,13 +2773,21 @@ void PTXABIInfo::computeInfo(CGFunctionInfo &FI) const { // Calling convention as default by an ABI. llvm::CallingConv::ID DefaultCC; - llvm::StringRef Env = getContext().Target.getTriple().getEnvironmentName(); - if (Env == "device") + const LangOptions &LangOpts = getContext().getLangOptions(); + if (LangOpts.OpenCL || LangOpts.CUDA) { + // If we are in OpenCL or CUDA mode, then default to device functions DefaultCC = llvm::CallingConv::PTX_Device; - else - DefaultCC = llvm::CallingConv::PTX_Kernel; - + } else { + // If we are in standard C/C++ mode, use the triple to decide on the default + StringRef Env = + getContext().getTargetInfo().getTriple().getEnvironmentName(); + if (Env == "device") + DefaultCC = llvm::CallingConv::PTX_Device; + else + DefaultCC = llvm::CallingConv::PTX_Kernel; + } FI.setEffectiveCallingConvention(DefaultCC); + } llvm::Value *PTXABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, @@ -2667,6 +2796,36 @@ llvm::Value *PTXABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, return 0; } +void PTXTargetCodeGenInfo::SetTargetAttributes(const Decl *D, + llvm::GlobalValue *GV, + CodeGen::CodeGenModule &M) const{ + const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); + if (!FD) return; + + llvm::Function *F = cast<llvm::Function>(GV); + + // Perform special handling in OpenCL mode + if (M.getLangOptions().OpenCL) { + // Use OpenCL function attributes to set proper calling conventions + // By default, all functions are device functions + if (FD->hasAttr<OpenCLKernelAttr>()) { + // OpenCL __kernel functions get a kernel calling convention + F->setCallingConv(llvm::CallingConv::PTX_Kernel); + // And kernel functions are not subject to inlining + F->addFnAttr(llvm::Attribute::NoInline); + } + } + + // Perform special handling in CUDA mode. + if (M.getLangOptions().CUDA) { + // CUDA __global__ functions get a kernel calling convention. Since + // __global__ functions cannot be called from the device, we do not + // need to set the noinline attribute. + if (FD->getAttr<CUDAGlobalAttr>()) + F->setCallingConv(llvm::CallingConv::PTX_Kernel); + } +} + } //===----------------------------------------------------------------------===// @@ -2891,7 +3050,7 @@ void MSP430TargetCodeGenInfo::SetTargetAttributes(const Decl *D, // Step 3: Emit ISR vector alias. unsigned Num = attr->getNumber() + 0xffe0; new llvm::GlobalAlias(GV->getType(), llvm::Function::ExternalLinkage, - "vector_" + llvm::Twine::utohexstr(Num), + "vector_" + Twine::utohexstr(Num), GV, &M.getModule()); } } @@ -2904,6 +3063,7 @@ void MSP430TargetCodeGenInfo::SetTargetAttributes(const Decl *D, namespace { class MipsABIInfo : public ABIInfo { + static const unsigned MinABIStackAlignInBytes = 4; public: MipsABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {} @@ -2914,10 +3074,13 @@ public: CodeGenFunction &CGF) const; }; +const unsigned MipsABIInfo::MinABIStackAlignInBytes; + class MIPSTargetCodeGenInfo : public TargetCodeGenInfo { + unsigned SizeOfUnwindException; public: - MIPSTargetCodeGenInfo(CodeGenTypes &CGT) - : TargetCodeGenInfo(new MipsABIInfo(CGT)) {} + MIPSTargetCodeGenInfo(CodeGenTypes &CGT, unsigned SZ) + : TargetCodeGenInfo(new MipsABIInfo(CGT)), SizeOfUnwindException(SZ) {} int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const { return 29; @@ -2925,6 +3088,10 @@ public: bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, llvm::Value *Address) const; + + unsigned getSizeOfUnwindException() const { + return SizeOfUnwindException; + } }; } @@ -2934,6 +3101,11 @@ ABIArgInfo MipsABIInfo::classifyArgumentType(QualType Ty) const { if (getContext().getTypeSize(Ty) == 0) return ABIArgInfo::getIgnore(); + // Records with non trivial destructors/constructors should not be passed + // by value. + if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty)) + return ABIArgInfo::getIndirect(0, /*ByVal=*/false); + return ABIArgInfo::getIndirect(0); } @@ -2973,7 +3145,37 @@ void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const { llvm::Value* MipsABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const { - return 0; + llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); + llvm::Type *BPP = llvm::PointerType::getUnqual(BP); + + CGBuilderTy &Builder = CGF.Builder; + llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap"); + llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur"); + unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8; + llvm::Type *PTy = llvm::PointerType::getUnqual(CGF.ConvertType(Ty)); + llvm::Value *AddrTyped; + + if (TypeAlign > MinABIStackAlignInBytes) { + llvm::Value *AddrAsInt32 = CGF.Builder.CreatePtrToInt(Addr, CGF.Int32Ty); + llvm::Value *Inc = llvm::ConstantInt::get(CGF.Int32Ty, TypeAlign - 1); + llvm::Value *Mask = llvm::ConstantInt::get(CGF.Int32Ty, -TypeAlign); + llvm::Value *Add = CGF.Builder.CreateAdd(AddrAsInt32, Inc); + llvm::Value *And = CGF.Builder.CreateAnd(Add, Mask); + AddrTyped = CGF.Builder.CreateIntToPtr(And, PTy); + } + else + AddrTyped = Builder.CreateBitCast(Addr, PTy); + + llvm::Value *AlignedAddr = Builder.CreateBitCast(AddrTyped, BP); + TypeAlign = std::max(TypeAlign, MinABIStackAlignInBytes); + uint64_t Offset = + llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, TypeAlign); + llvm::Value *NextAddr = + Builder.CreateGEP(AlignedAddr, llvm::ConstantInt::get(CGF.Int32Ty, Offset), + "ap.next"); + Builder.CreateStore(NextAddr, VAListAddrAsBPP); + + return AddrTyped; } bool @@ -2987,7 +3189,7 @@ MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, // Everything on MIPS is 4 bytes. Double-precision FP registers // are aliased to pairs of single-precision FP registers. - const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); + llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4); // 0-31 are the general purpose registers, $0 - $31. @@ -3009,29 +3211,98 @@ MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, return false; } +//===----------------------------------------------------------------------===// +// TCE ABI Implementation (see http://tce.cs.tut.fi). Uses mostly the defaults. +// Currently subclassed only to implement custom OpenCL C function attribute +// handling. +//===----------------------------------------------------------------------===// + +namespace { + +class TCETargetCodeGenInfo : public DefaultTargetCodeGenInfo { +public: + TCETargetCodeGenInfo(CodeGenTypes &CGT) + : DefaultTargetCodeGenInfo(CGT) {} + + virtual void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV, + CodeGen::CodeGenModule &M) const; +}; + +void TCETargetCodeGenInfo::SetTargetAttributes(const Decl *D, + llvm::GlobalValue *GV, + CodeGen::CodeGenModule &M) const { + const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); + if (!FD) return; + + llvm::Function *F = cast<llvm::Function>(GV); + + if (M.getLangOptions().OpenCL) { + if (FD->hasAttr<OpenCLKernelAttr>()) { + // OpenCL C Kernel functions are not subject to inlining + F->addFnAttr(llvm::Attribute::NoInline); + + if (FD->hasAttr<ReqdWorkGroupSizeAttr>()) { + + // Convert the reqd_work_group_size() attributes to metadata. + llvm::LLVMContext &Context = F->getContext(); + llvm::NamedMDNode *OpenCLMetadata = + M.getModule().getOrInsertNamedMetadata("opencl.kernel_wg_size_info"); + + SmallVector<llvm::Value*, 5> Operands; + Operands.push_back(F); + + Operands.push_back(llvm::Constant::getIntegerValue( + llvm::Type::getInt32Ty(Context), + llvm::APInt( + 32, + FD->getAttr<ReqdWorkGroupSizeAttr>()->getXDim()))); + Operands.push_back(llvm::Constant::getIntegerValue( + llvm::Type::getInt32Ty(Context), + llvm::APInt( + 32, + FD->getAttr<ReqdWorkGroupSizeAttr>()->getYDim()))); + Operands.push_back(llvm::Constant::getIntegerValue( + llvm::Type::getInt32Ty(Context), + llvm::APInt( + 32, + FD->getAttr<ReqdWorkGroupSizeAttr>()->getZDim()))); + + // Add a boolean constant operand for "required" (true) or "hint" (false) + // for implementing the work_group_size_hint attr later. Currently + // always true as the hint is not yet implemented. + Operands.push_back(llvm::ConstantInt::getTrue(llvm::Type::getInt1Ty(Context))); + + OpenCLMetadata->addOperand(llvm::MDNode::get(Context, Operands)); + } + } + } +} + +} const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { if (TheTargetCodeGenInfo) return *TheTargetCodeGenInfo; - // For now we just cache the TargetCodeGenInfo in CodeGenModule and don't - // free it. - - const llvm::Triple &Triple = getContext().Target.getTriple(); + const llvm::Triple &Triple = getContext().getTargetInfo().getTriple(); switch (Triple.getArch()) { default: return *(TheTargetCodeGenInfo = new DefaultTargetCodeGenInfo(Types)); case llvm::Triple::mips: case llvm::Triple::mipsel: - return *(TheTargetCodeGenInfo = new MIPSTargetCodeGenInfo(Types)); + return *(TheTargetCodeGenInfo = new MIPSTargetCodeGenInfo(Types, 24)); + + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + return *(TheTargetCodeGenInfo = new MIPSTargetCodeGenInfo(Types, 32)); case llvm::Triple::arm: case llvm::Triple::thumb: { ARMABIInfo::ABIKind Kind = ARMABIInfo::AAPCS; - if (strcmp(getContext().Target.getABI(), "apcs-gnu") == 0) + if (strcmp(getContext().getTargetInfo().getABI(), "apcs-gnu") == 0) Kind = ARMABIInfo::APCS; else if (CodeGenOpts.FloatABI == "hard") Kind = ARMABIInfo::AAPCS_VFP; @@ -3055,8 +3326,11 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { case llvm::Triple::msp430: return *(TheTargetCodeGenInfo = new MSP430TargetCodeGenInfo(Types)); + case llvm::Triple::tce: + return *(TheTargetCodeGenInfo = new TCETargetCodeGenInfo(Types)); + case llvm::Triple::x86: { - bool DisableMMX = strcmp(getContext().Target.getABI(), "no-mmx") == 0; + bool DisableMMX = strcmp(getContext().getTargetInfo().getABI(), "no-mmx") == 0; if (Triple.isOSDarwin()) return *(TheTargetCodeGenInfo = |