diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index ba925275faba6..097f561575a0c 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -2562,6 +2562,15 @@ struct MemorySanitizerVisitor : public InstVisitor { Value *CreateShadowCast(IRBuilder<> &IRB, Value *V, Type *dstTy, bool Signed = false) { Type *srcTy = V->getType(); + + // Shadow types should never be floating-point. + assert(!srcTy->isFPOrFPVectorTy()); + assert(!dstTy->isFPOrFPVectorTy()); + + // TODO (though never needed in practice) + assert(!srcTy->isArrayTy()); + assert(!dstTy->isArrayTy()); + if (srcTy == dstTy) return V; size_t srcSizeInBits = VectorOrPrimitiveTypeSizeInBits(srcTy); @@ -2571,15 +2580,34 @@ struct MemorySanitizerVisitor : public InstVisitor { if (dstTy->isIntegerTy() && srcTy->isIntegerTy()) return IRB.CreateIntCast(V, dstTy, Signed); + if (dstTy->isVectorTy() && srcTy->isVectorTy() && cast(dstTy)->getElementCount() == cast(srcTy)->getElementCount()) + // We rely on the assertion at the start of the function that neither + // type is a floating-point vector. return IRB.CreateIntCast(V, dstTy, Signed); + + if (dstTy->isStructTy() && srcTy->isStructTy() && + cast(dstTy)->getNumElements() == + cast(srcTy)->getNumElements()) { + Value *DStruct = PoisonValue::get(dstTy); + + for (unsigned i = 0, n = cast(dstTy)->getNumElements(); i < n; + i++) { + Value *Elem = IRB.CreateExtractValue(V, i); + Type *ElemDstTy = cast(dstTy)->getElementType(i); + Value *ElemDst = CreateShadowCast(IRB, Elem, ElemDstTy, Signed); + DStruct = IRB.CreateInsertValue(DStruct, ElemDst, i); + } + + return DStruct; + } + Value *V1 = IRB.CreateBitCast(V, Type::getIntNTy(*MS.C, srcSizeInBits)); Value *V2 = IRB.CreateIntCast(V1, Type::getIntNTy(*MS.C, dstSizeInBits), Signed); return IRB.CreateBitCast(V2, dstTy); - // TODO: handle struct types. } /// Cast an application value to the type of its own shadow.