mirror of
https://github.com/RPCS3/llvm.git
synced 2025-04-02 13:21:43 +00:00
[msan] Fix handling of byval arguments in VarArg calls.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203794 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b9aefe6d09
commit
2da418712c
@ -2328,27 +2328,40 @@ struct VarArgAMD64Helper : public VarArgHelper {
|
||||
for (CallSite::arg_iterator ArgIt = CS.arg_begin(), End = CS.arg_end();
|
||||
ArgIt != End; ++ArgIt) {
|
||||
Value *A = *ArgIt;
|
||||
ArgKind AK = classifyArgument(A);
|
||||
if (AK == AK_GeneralPurpose && GpOffset >= AMD64GpEndOffset)
|
||||
AK = AK_Memory;
|
||||
if (AK == AK_FloatingPoint && FpOffset >= AMD64FpEndOffset)
|
||||
AK = AK_Memory;
|
||||
Value *Base;
|
||||
switch (AK) {
|
||||
case AK_GeneralPurpose:
|
||||
Base = getShadowPtrForVAArgument(A, IRB, GpOffset);
|
||||
GpOffset += 8;
|
||||
break;
|
||||
case AK_FloatingPoint:
|
||||
Base = getShadowPtrForVAArgument(A, IRB, FpOffset);
|
||||
FpOffset += 16;
|
||||
break;
|
||||
case AK_Memory:
|
||||
uint64_t ArgSize = MS.DL->getTypeAllocSize(A->getType());
|
||||
Base = getShadowPtrForVAArgument(A, IRB, OverflowOffset);
|
||||
unsigned ArgNo = CS.getArgumentNo(ArgIt);
|
||||
bool IsByVal = CS.paramHasAttr(ArgNo + 1, Attribute::ByVal);
|
||||
if (IsByVal) {
|
||||
// ByVal arguments always go to the overflow area.
|
||||
assert(A->getType()->isPointerTy());
|
||||
Type *RealTy = A->getType()->getPointerElementType();
|
||||
uint64_t ArgSize = MS.DL->getTypeAllocSize(RealTy);
|
||||
Value *Base = getShadowPtrForVAArgument(RealTy, IRB, OverflowOffset);
|
||||
OverflowOffset += DataLayout::RoundUpAlignment(ArgSize, 8);
|
||||
IRB.CreateMemCpy(Base, MSV.getShadowPtr(A, IRB.getInt8Ty(), IRB),
|
||||
ArgSize, kShadowTLSAlignment);
|
||||
} else {
|
||||
ArgKind AK = classifyArgument(A);
|
||||
if (AK == AK_GeneralPurpose && GpOffset >= AMD64GpEndOffset)
|
||||
AK = AK_Memory;
|
||||
if (AK == AK_FloatingPoint && FpOffset >= AMD64FpEndOffset)
|
||||
AK = AK_Memory;
|
||||
Value *Base;
|
||||
switch (AK) {
|
||||
case AK_GeneralPurpose:
|
||||
Base = getShadowPtrForVAArgument(A->getType(), IRB, GpOffset);
|
||||
GpOffset += 8;
|
||||
break;
|
||||
case AK_FloatingPoint:
|
||||
Base = getShadowPtrForVAArgument(A->getType(), IRB, FpOffset);
|
||||
FpOffset += 16;
|
||||
break;
|
||||
case AK_Memory:
|
||||
uint64_t ArgSize = MS.DL->getTypeAllocSize(A->getType());
|
||||
Base = getShadowPtrForVAArgument(A->getType(), IRB, OverflowOffset);
|
||||
OverflowOffset += DataLayout::RoundUpAlignment(ArgSize, 8);
|
||||
}
|
||||
IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment);
|
||||
}
|
||||
IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment);
|
||||
}
|
||||
Constant *OverflowSize =
|
||||
ConstantInt::get(IRB.getInt64Ty(), OverflowOffset - AMD64FpEndOffset);
|
||||
@ -2356,11 +2369,11 @@ struct VarArgAMD64Helper : public VarArgHelper {
|
||||
}
|
||||
|
||||
/// \brief Compute the shadow address for a given va_arg.
|
||||
Value *getShadowPtrForVAArgument(Value *A, IRBuilder<> &IRB,
|
||||
Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB,
|
||||
int ArgOffset) {
|
||||
Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy);
|
||||
Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
|
||||
return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(A), 0),
|
||||
return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0),
|
||||
"_msarg");
|
||||
}
|
||||
|
||||
|
@ -765,3 +765,45 @@ entry:
|
||||
; Second element app value
|
||||
; CHECK-ORIGINS: insertvalue { i64, i32 } {{.*}}, i32 {{.*}}, 1
|
||||
; CHECK-ORIGINS: ret { i64, i32 }
|
||||
|
||||
|
||||
; Test shadow propagation for aggregates passed through ellipsis.
|
||||
|
||||
%struct.StructByVal = type { i32, i32, i32, i32 }
|
||||
|
||||
declare void @VAArgStructFn(i32 %guard, ...)
|
||||
|
||||
define void @VAArgStruct(%struct.StructByVal* nocapture %s) sanitize_memory {
|
||||
entry:
|
||||
%agg.tmp2 = alloca %struct.StructByVal, align 8
|
||||
%0 = bitcast %struct.StructByVal* %s to i8*
|
||||
%agg.tmp.sroa.0.0..sroa_cast = bitcast %struct.StructByVal* %s to i64*
|
||||
%agg.tmp.sroa.0.0.copyload = load i64* %agg.tmp.sroa.0.0..sroa_cast, align 4
|
||||
%agg.tmp.sroa.2.0..sroa_idx = getelementptr inbounds %struct.StructByVal* %s, i64 0, i32 2
|
||||
%agg.tmp.sroa.2.0..sroa_cast = bitcast i32* %agg.tmp.sroa.2.0..sroa_idx to i64*
|
||||
%agg.tmp.sroa.2.0.copyload = load i64* %agg.tmp.sroa.2.0..sroa_cast, align 4
|
||||
%1 = bitcast %struct.StructByVal* %agg.tmp2 to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* %0, i64 16, i32 4, i1 false)
|
||||
call void (i32, ...)* @VAArgStructFn(i32 undef, i64 %agg.tmp.sroa.0.0.copyload, i64 %agg.tmp.sroa.2.0.copyload, i64 %agg.tmp.sroa.0.0.copyload, i64 %agg.tmp.sroa.2.0.copyload, %struct.StructByVal* byval align 8 %agg.tmp2)
|
||||
ret void
|
||||
}
|
||||
|
||||
; "undef" and the first 2 structs go to general purpose registers;
|
||||
; the third struct goes to the overflow area byval
|
||||
|
||||
; CHECK: @VAArgStruct
|
||||
; undef
|
||||
; CHECK: store i32 -1, i32* {{.*}}@__msan_va_arg_tls {{.*}}, align 8
|
||||
; first struct through general purpose registers
|
||||
; CHECK: store i64 {{.*}}, i64* {{.*}}@__msan_va_arg_tls{{.*}}, i64 8){{.*}}, align 8
|
||||
; CHECK: store i64 {{.*}}, i64* {{.*}}@__msan_va_arg_tls{{.*}}, i64 16){{.*}}, align 8
|
||||
; second struct through general purpose registers
|
||||
; CHECK: store i64 {{.*}}, i64* {{.*}}@__msan_va_arg_tls{{.*}}, i64 24){{.*}}, align 8
|
||||
; CHECK: store i64 {{.*}}, i64* {{.*}}@__msan_va_arg_tls{{.*}}, i64 32){{.*}}, align 8
|
||||
; third struct through the overflow area byval
|
||||
; CHECK: ptrtoint %struct.StructByVal* {{.*}} to i64
|
||||
; CHECK: bitcast { i32, i32, i32, i32 }* {{.*}}@__msan_va_arg_tls {{.*}}, i64 176
|
||||
; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
|
||||
; CHECK: store i64 16, i64* @__msan_va_arg_overflow_size_tls
|
||||
; CHECK: call void (i32, ...)* @VAArgStructFn
|
||||
; CHECK: ret void
|
||||
|
Loading…
x
Reference in New Issue
Block a user