Index: lib/Transforms/Instrumentation/MemorySanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -718,14 +718,36 @@ IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()), Origin}); } else { - Value *Cmp = IRB.CreateICmpNE( - ConvertedShadow, getCleanShadow(ConvertedShadow), "_mscmp"); - Instruction *CheckTerm = SplitBlockAndInsertIfThen( - Cmp, &*IRB.GetInsertPoint(), false, MS.OriginStoreWeights); - IRBuilder<> IRBNew(CheckTerm); - paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), - getOriginPtr(Addr, IRBNew, Alignment), StoreSize, - OriginAlignment); + if (ArrayType *AT = dyn_cast(ConvertedShadow->getType())) { + // For ArrayType we need to apply the icmp to each element (since the + // the instruction does not support array types). + Value *CleanShadow = getCleanShadow(ConvertedShadow); + for (int i = 0, s = AT->getNumElements(); i < s; i++) { + Value *ConvertedShadowElem = IRB.CreateExtractValue( + ConvertedShadow, i); + Value *CleanShadowElem = IRB.CreateExtractValue(CleanShadow, i); + Value *Cmp = IRB.CreateICmpNE( + ConvertedShadowElem, CleanShadowElem, "_mscmp"); + + Instruction *CheckTerm = SplitBlockAndInsertIfThen( + Cmp, &*IRB.GetInsertPoint(), false, MS.OriginStoreWeights); + IRB.SetInsertPoint(CheckTerm); + + IRBuilder<> IRBNew(CheckTerm); + paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), + getOriginPtr(Addr, IRBNew, Alignment), StoreSize, + OriginAlignment); + } + } else { + Value *Cmp = IRB.CreateICmpNE( + ConvertedShadow, getCleanShadow(ConvertedShadow), "_mscmp"); + Instruction *CheckTerm = SplitBlockAndInsertIfThen( + Cmp, &*IRB.GetInsertPoint(), false, MS.OriginStoreWeights); + IRBuilder<> IRBNew(CheckTerm); + paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), + getOriginPtr(Addr, IRBNew, Alignment), StoreSize, + OriginAlignment); + } } } } Index: test/Instrumentation/MemorySanitizer/origin-array.ll =================================================================== --- /dev/null +++ test/Instrumentation/MemorySanitizer/origin-array.ll @@ -0,0 +1,72 @@ +; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=2 -S | FileCheck %s + +target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" +target triple = "aarch64-unknown-linux-gnu" + +; Check origin handling of array types. Since the instrumentation will +; potentially creates icmp instruction to check origin values, it requires +; the intrumentation pass to create icmp for each element. + +%struct.mypair = type { i64, i32 } + +; Function Attrs: nounwind +define [2 x i64] @_Z12my_make_pairli(i64 %x, i32 %y) { +entry: + %retval = alloca %struct.mypair, align 8 + %x.addr = alloca i64, align 8 + %y.addr = alloca i32, align 4 + store i64 %x, i64* %x.addr, align 8 + store i32 %y, i32* %y.addr, align 4 + %0 = load i64, i64* %x.addr, align 8 + %x1 = getelementptr inbounds %struct.mypair, %struct.mypair* %retval, i32 0, i32 0 + store i64 %0, i64* %x1, align 8 + %1 = load i32, i32* %y.addr, align 4 + %y2 = getelementptr inbounds %struct.mypair, %struct.mypair* %retval, i32 0, i32 1 + store i32 %1, i32* %y2, align 8 + %2 = bitcast %struct.mypair* %retval to [2 x i64]* + %3 = load [2 x i64], [2 x i64]* %2, align 8 + ret [2 x i64] %3 +} + +; Function Attrs: nounwind +define i32 @_Z3fooi(i32 %p) #0 { +entry: + %p.addr = alloca i32, align 4 + %z = alloca %struct.mypair, align 8 + store i32 %p, i32* %p.addr, align 4 + %0 = load i32, i32* %p.addr, align 4 + %conv = sext i32 %0 to i64 + %call = call [2 x i64] @_Z12my_make_pairli(i64 %conv, i32 0) + %1 = bitcast %struct.mypair* %z to [2 x i64]* + store [2 x i64] %call, [2 x i64]* %1, align 8 + %x = getelementptr inbounds %struct.mypair, %struct.mypair* %z, i32 0, i32 0 + %2 = load i64, i64* %x, align 8 + %y = getelementptr inbounds %struct.mypair, %struct.mypair* %z, i32 0, i32 1 + %3 = load i32, i32* %y, align 8 + %conv1 = sext i32 %3 to i64 + %add = add nsw i64 %2, %conv1 + %conv2 = trunc i64 %add to i32 + ret i32 %conv2 +} + +; CHECK-LABEL: @_Z3fooi +; CHECK: load {{.*}} @__msan_param_tls +; CHECK: [[ORIGIN:%[01-9a-z]+]] = load {{.*}} @__msan_retval_origin_tls +; CHECK: store {{.*}} + +; Extract and compare the first element. +; CHECK: {{.*}} extractvalue {{.*}} 0 +; CHECK: icmp +; CHECK: br i1 {{.*}} +; CHECK: ;