diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-01-15 22:31:35 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-01-15 22:31:35 +0000 |
commit | 30d791273d07fac9c0c1641a0731191bca6e8606 (patch) | |
tree | 6c840e234e0c97d0adf033bb41f667a5f5b528b6 /lib/CodeGen | |
parent | 9f4dbff6669c8037f3b036bcf580d14f1a4f12a5 (diff) | |
download | src-30d791273d07fac9c0c1641a0731191bca6e8606.tar.gz src-30d791273d07fac9c0c1641a0731191bca6e8606.zip |
Notes
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 12 | ||||
-rw-r--r-- | lib/CodeGen/TargetInfo.cpp | 47 |
2 files changed, 44 insertions, 15 deletions
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 9e0fbcfd1844..140e9aa3445f 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -3216,18 +3216,26 @@ Value *ScalarExprEmitter::VisitChooseExpr(ChooseExpr *E) { Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { QualType Ty = VE->getType(); + if (Ty->isVariablyModifiedType()) CGF.EmitVariablyModifiedType(Ty); llvm::Value *ArgValue = CGF.EmitVAListRef(VE->getSubExpr()); llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType()); + llvm::Type *ArgTy = ConvertType(VE->getType()); // If EmitVAArg fails, we fall back to the LLVM instruction. if (!ArgPtr) - return Builder.CreateVAArg(ArgValue, ConvertType(VE->getType())); + return Builder.CreateVAArg(ArgValue, ArgTy); // FIXME Volatility. - return Builder.CreateLoad(ArgPtr); + llvm::Value *Val = Builder.CreateLoad(ArgPtr); + + // If EmitVAArg promoted the type, we must truncate it. + if (ArgTy != Val->getType()) + Val = Builder.CreateTrunc(Val, ArgTy); + + return Val; } Value *ScalarExprEmitter::VisitBlockExpr(const BlockExpr *block) { diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 5da22c3e6cbb..f75e59d6f2d8 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -5446,15 +5446,19 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const { // If we have reached here, aggregates are passed directly by coercing to // another structure type. Padding is inserted if the offset of the // aggregate is unaligned. - return ABIArgInfo::getDirect(HandleAggregates(Ty, TySize), 0, - getPaddingType(OrigOffset, CurrOffset)); + ABIArgInfo ArgInfo = + ABIArgInfo::getDirect(HandleAggregates(Ty, TySize), 0, + getPaddingType(OrigOffset, CurrOffset)); + ArgInfo.setInReg(true); + return ArgInfo; } // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs<EnumType>()) Ty = EnumTy->getDecl()->getIntegerType(); - if (Ty->isPromotableIntegerType()) + // All integral types are promoted to the GPR width. + if (Ty->isIntegralOrEnumerationType()) return ABIArgInfo::getExtend(); return ABIArgInfo::getDirect( @@ -5506,7 +5510,12 @@ MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const { ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const { uint64_t Size = getContext().getTypeSize(RetTy); - if (RetTy->isVoidType() || Size == 0) + if (RetTy->isVoidType()) + return ABIArgInfo::getIgnore(); + + // O32 doesn't treat zero-sized structs differently from other structs. + // However, N32/N64 ignores zero sized return values. + if (!IsO32 && Size == 0) return ABIArgInfo::getIgnore(); if (isAggregateTypeForABI(RetTy) || RetTy->isVectorType()) { @@ -5514,12 +5523,15 @@ ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const { if (RetTy->isAnyComplexType()) return ABIArgInfo::getDirect(); - // O32 returns integer vectors in registers. - if (IsO32 && RetTy->isVectorType() && !RetTy->hasFloatingRepresentation()) - return ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size)); - - if (!IsO32) - return ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size)); + // O32 returns integer vectors in registers and N32/N64 returns all small + // aggregates in registers.. + if (!IsO32 || + (RetTy->isVectorType() && !RetTy->hasFloatingRepresentation())) { + ABIArgInfo ArgInfo = + ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size)); + ArgInfo.setInReg(true); + return ArgInfo; + } } return ABIArgInfo::getIndirect(0); @@ -5549,11 +5561,20 @@ llvm::Value* MipsABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const { llvm::Type *BP = CGF.Int8PtrTy; llvm::Type *BPP = CGF.Int8PtrPtrTy; + + // Integer arguments are promoted 32-bit on O32 and 64-bit on N32/N64. + unsigned SlotSizeInBits = IsO32 ? 32 : 64; + if (Ty->isIntegerType() && + CGF.getContext().getIntWidth(Ty) < SlotSizeInBits) { + Ty = CGF.getContext().getIntTypeForBitwidth(SlotSizeInBits, + Ty->isSignedIntegerType()); + } CGBuilderTy &Builder = CGF.Builder; llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap"); llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur"); - int64_t TypeAlign = getContext().getTypeAlign(Ty) / 8; + int64_t TypeAlign = + std::min(getContext().getTypeAlign(Ty) / 8, StackAlignInBytes); llvm::Type *PTy = llvm::PointerType::getUnqual(CGF.ConvertType(Ty)); llvm::Value *AddrTyped; unsigned PtrWidth = getTarget().getPointerWidth(0); @@ -5572,8 +5593,8 @@ llvm::Value* MipsABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, llvm::Value *AlignedAddr = Builder.CreateBitCast(AddrTyped, BP); TypeAlign = std::max((unsigned)TypeAlign, MinABIStackAlignInBytes); - uint64_t Offset = - llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, TypeAlign); + unsigned ArgSizeInBits = CGF.getContext().getTypeSize(Ty); + uint64_t Offset = llvm::RoundUpToAlignment(ArgSizeInBits / 8, TypeAlign); llvm::Value *NextAddr = Builder.CreateGEP(AlignedAddr, llvm::ConstantInt::get(IntTy, Offset), "ap.next"); |