diff options
author | Chris Lattner <sabre@nondot.org> | 2010-07-30 04:02:24 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-07-30 04:02:24 +0000 |
commit | 117e3f4cd4d6ea41c3202da8729f94168c5c8239 (patch) | |
tree | 0425d5c3eddc8a6b289b382ef947aaf875985210 /lib/CodeGen/CGCall.cpp | |
parent | 98406a953a00a96a7a2fad5509fde1bfc7b15e3d (diff) |
fix PR5179 and correctly fix PR5831 to not miscompile.
The X86-64 ABI code didn't handle the case when a struct
would get classified and turn up as "NoClass INTEGER" for
example. This is perfectly possible when the first slot
is all padding (e.g. due to empty base classes). In this
situation, the first 8-byte doesn't take a register at all,
only the second 8-byte does.
This fixes this by enhancing the x86-64 abi stuff to allow
and handle this case, reverts the broken fix for PR5831,
and enhances the target independent stuff to be able to
handle an argument value in registers being accessed at an
offset from the memory value.
This is the last x86-64 calling convention related miscompile
that I'm aware of.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109848 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGCall.cpp')
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 56 |
1 files changed, 47 insertions, 9 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 94a2ae9ee6..2ba44714c7 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -869,7 +869,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, case ABIArgInfo::Direct: { // If we have the trivial case, handle it with no muss and fuss. if (!isa<llvm::StructType>(ArgI.getCoerceToType()) && - ArgI.getCoerceToType() == ConvertType(Ty)) { + ArgI.getCoerceToType() == ConvertType(Ty) && + ArgI.getDirectOffset() == 0) { assert(AI != Fn->arg_end() && "Argument mismatch!"); llvm::Value *V = AI; @@ -896,13 +897,21 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, Alloca->setAlignment(AlignmentToUse); llvm::Value *V = Alloca; + llvm::Value *Ptr = V; // Pointer to store into. + + // If the value is offset in memory, apply the offset now. + if (unsigned Offs = ArgI.getDirectOffset()) { + Ptr = Builder.CreateBitCast(Ptr, Builder.getInt8PtrTy()); + Ptr = Builder.CreateConstGEP1_32(Ptr, Offs); + Ptr = Builder.CreateBitCast(Ptr, + llvm::PointerType::getUnqual(ArgI.getCoerceToType())); + } // If the coerce-to type is a first class aggregate, we flatten it and // pass the elements. Either way is semantically identical, but fast-isel // and the optimizer generally likes scalar values better than FCAs. if (const llvm::StructType *STy = dyn_cast<llvm::StructType>(ArgI.getCoerceToType())) { - llvm::Value *Ptr = V; Ptr = Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(STy)); for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { @@ -915,7 +924,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, // Simple case, just do a coerced store of the argument into the alloca. assert(AI != Fn->arg_end() && "Argument mismatch!"); AI->setName(Arg->getName() + ".coerce"); - CreateCoercedStore(AI++, V, /*DestIsVolatile=*/false, *this); + CreateCoercedStore(AI++, Ptr, /*DestIsVolatile=*/false, *this); } @@ -992,8 +1001,8 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI) { case ABIArgInfo::Extend: case ABIArgInfo::Direct: - - if (RetAI.getCoerceToType() == ConvertType(RetTy)) { + if (RetAI.getCoerceToType() == ConvertType(RetTy) && + RetAI.getDirectOffset() == 0) { // The internal return value temp always will have pointer-to-return-type // type, just do a load. @@ -1019,7 +1028,16 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI) { } } } else { - RV = CreateCoercedLoad(ReturnValue, RetAI.getCoerceToType(), *this); + llvm::Value *V = ReturnValue; + // If the value is offset in memory, apply the offset now. + if (unsigned Offs = RetAI.getDirectOffset()) { + V = Builder.CreateBitCast(V, Builder.getInt8PtrTy()); + V = Builder.CreateConstGEP1_32(V, Offs); + V = Builder.CreateBitCast(V, + llvm::PointerType::getUnqual(RetAI.getCoerceToType())); + } + + RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), *this); } break; @@ -1142,7 +1160,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, case ABIArgInfo::Extend: case ABIArgInfo::Direct: { if (!isa<llvm::StructType>(ArgInfo.getCoerceToType()) && - ArgInfo.getCoerceToType() == ConvertType(info_it->type)) { + ArgInfo.getCoerceToType() == ConvertType(info_it->type) && + ArgInfo.getDirectOffset() == 0) { if (RV.isScalar()) Args.push_back(RV.getScalarVal()); else @@ -1161,6 +1180,15 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } else SrcPtr = RV.getAggregateAddr(); + // If the value is offset in memory, apply the offset now. + if (unsigned Offs = ArgInfo.getDirectOffset()) { + SrcPtr = Builder.CreateBitCast(SrcPtr, Builder.getInt8PtrTy()); + SrcPtr = Builder.CreateConstGEP1_32(SrcPtr, Offs); + SrcPtr = Builder.CreateBitCast(SrcPtr, + llvm::PointerType::getUnqual(ArgInfo.getCoerceToType())); + + } + // If the coerce-to type is a first class aggregate, we flatten it and // pass the elements. Either way is semantically identical, but fast-isel // and the optimizer generally likes scalar values better than FCAs. @@ -1280,7 +1308,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, case ABIArgInfo::Extend: case ABIArgInfo::Direct: { - if (RetAI.getCoerceToType() == ConvertType(RetTy)) { + if (RetAI.getCoerceToType() == ConvertType(RetTy) && + RetAI.getDirectOffset() == 0) { if (RetTy->isAnyComplexType()) { llvm::Value *Real = Builder.CreateExtractValue(CI, 0); llvm::Value *Imag = Builder.CreateExtractValue(CI, 1); @@ -1308,7 +1337,16 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, DestIsVolatile = false; } - CreateCoercedStore(CI, DestPtr, DestIsVolatile, *this); + // If the value is offset in memory, apply the offset now. + llvm::Value *StorePtr = DestPtr; + if (unsigned Offs = RetAI.getDirectOffset()) { + StorePtr = Builder.CreateBitCast(StorePtr, Builder.getInt8PtrTy()); + StorePtr = Builder.CreateConstGEP1_32(StorePtr, Offs); + StorePtr = Builder.CreateBitCast(StorePtr, + llvm::PointerType::getUnqual(RetAI.getCoerceToType())); + } + CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this); + if (RetTy->isAnyComplexType()) return RValue::getComplex(LoadComplexFromAddr(DestPtr, false)); if (CodeGenFunction::hasAggregateLLVMType(RetTy)) |