[compiler-rt] [llvm] [msan] Add 32-bit platforms support (PR #109284)
Vitaly Buka via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 12 00:47:36 PST 2024
================
@@ -6004,37 +6024,152 @@ struct VarArgSystemZHelper : public VarArgHelperBase {
}
};
-/// MIPS-specific implementation of VarArgHelper.
-/// NOTE: This is also used for LoongArch64.
+/// i386-specific implementation of VarArgHelper.
+struct VarArgI386Helper : public VarArgHelperBase {
+ AllocaInst *VAArgTLSCopy = nullptr;
+ Value *VAArgSize = nullptr;
+ const DataLayout &DL = F.getDataLayout();
+ unsigned IntptrSize = DL.getTypeStoreSize(MS.IntptrTy);
+
+ VarArgI386Helper(Function &F, MemorySanitizer &MS,
+ MemorySanitizerVisitor &MSV)
+ : VarArgHelperBase(F, MS, MSV, /*VAListTagSize=*/4) {}
+
+ void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {
+ unsigned VAArgOffset = 0;
+ for (const auto &[ArgNo, A] : llvm::enumerate(CB.args())) {
+ bool IsFixed = ArgNo < CB.getFunctionType()->getNumParams();
+ bool IsByVal = CB.paramHasAttr(ArgNo, Attribute::ByVal);
+ if (IsByVal) {
+ assert(A->getType()->isPointerTy());
+ Type *RealTy = CB.getParamByValType(ArgNo);
+ uint64_t ArgSize = DL.getTypeAllocSize(RealTy);
+ Align ArgAlign = CB.getParamAlign(ArgNo).value_or(Align(IntptrSize));
+ if (ArgAlign < IntptrSize)
+ ArgAlign = Align(IntptrSize);
+ VAArgOffset = alignTo(VAArgOffset, ArgAlign);
+ if (!IsFixed) {
+ Value *Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
+ if (Base) {
+ Value *AShadowPtr, *AOriginPtr;
+ std::tie(AShadowPtr, AOriginPtr) =
+ MSV.getShadowOriginPtr(A, IRB, IRB.getInt8Ty(),
+ kShadowTLSAlignment, /*isStore*/ false);
+
+ IRB.CreateMemCpy(Base, kShadowTLSAlignment, AShadowPtr,
+ kShadowTLSAlignment, ArgSize);
+ }
+ VAArgOffset += alignTo(ArgSize, Align(IntptrSize));
+ }
+ } else {
+ Value *Base;
+ uint64_t ArgSize = DL.getTypeAllocSize(A->getType());
+ Align ArgAlign = Align(IntptrSize);
+ VAArgOffset = alignTo(VAArgOffset, ArgAlign);
+ if (DL.isBigEndian()) {
+ // Adjusting the shadow for argument with size < IntptrSize to match
+ // the placement of bits in big endian system
+ if (ArgSize < IntptrSize)
+ VAArgOffset += (IntptrSize - ArgSize);
+ }
+ if (!IsFixed) {
+ Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
+ if (Base)
+ IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment);
+ VAArgOffset += ArgSize;
+ VAArgOffset = alignTo(VAArgOffset, Align(IntptrSize));
+ }
+ }
+ }
+
+ Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
+ // Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of
+ // a new class member i.e. it is the total size of all VarArgs.
+ IRB.CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
+ }
+
+ void finalizeInstrumentation() override {
+ assert(!VAArgSize && !VAArgTLSCopy &&
+ "finalizeInstrumentation called twice");
+
+ IRBuilder<> IRB(MSV.FnPrologueEnd);
+ VAArgSize = IRB.CreateLoad(IRB.getInt64Ty(), MS.VAArgOverflowSizeTLS);
+ Value *CopySize = IRB.CreateAdd(
+ ConstantInt::get(MS.IntptrTy, 0),
+ IRB.CreateIntCast(VAArgSize, MS.IntptrTy, /*isSigned*/ false));
+
+ if (!VAStartInstrumentationList.empty()) {
+ // If there is a va_start in this function, make a backup copy of
+ // va_arg_tls somewhere in the function entry block.
+ VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
+ VAArgTLSCopy->setAlignment(kShadowTLSAlignment);
+ IRB.CreateMemSet(VAArgTLSCopy, Constant::getNullValue(IRB.getInt8Ty()),
+ CopySize, kShadowTLSAlignment, false);
+
+ Value *SrcSize = IRB.CreateBinaryIntrinsic(
+ Intrinsic::umin, CopySize,
+ ConstantInt::get(MS.IntptrTy, kParamTLSSize));
+ IRB.CreateMemCpy(VAArgTLSCopy, kShadowTLSAlignment, MS.VAArgTLS,
+ kShadowTLSAlignment, SrcSize);
+ }
+
+ // Instrument va_start.
+ // Copy va_list shadow from the backup copy of the TLS contents.
+ for (size_t i = 0, n = VAStartInstrumentationList.size(); i < n; i++) {
+ CallInst *OrigInst = VAStartInstrumentationList[i];
+ NextNodeIRBuilder IRB(OrigInst);
+ Value *VAListTag = OrigInst->getArgOperand(0);
+ Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
+ Value *RegSaveAreaPtrPtr =
+ IRB.CreateIntToPtr(IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),
+ PointerType::get(RegSaveAreaPtrTy, 0));
+ Value *RegSaveAreaPtr =
+ IRB.CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
+ Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
+ const Align Alignment = Align(IntptrSize);
+ std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
+ MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.getInt8Ty(),
+ Alignment, /*isStore*/ true);
+ IRB.CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
+ CopySize);
+ }
+ }
+};
+
+/// Implementation of VarArgHelper that is used for ARM32, MIPS, RISCV,
+/// LoongArch64.
struct VarArgGenericHelper : public VarArgHelperBase {
AllocaInst *VAArgTLSCopy = nullptr;
Value *VAArgSize = nullptr;
+ const DataLayout &DL = F.getDataLayout();
+ unsigned IntptrSize = DL.getTypeStoreSize(MS.IntptrTy);
VarArgGenericHelper(Function &F, MemorySanitizer &MS,
MemorySanitizerVisitor &MSV, const unsigned VAListTagSize)
: VarArgHelperBase(F, MS, MSV, VAListTagSize) {}
void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {
unsigned VAArgOffset = 0;
- const DataLayout &DL = F.getDataLayout();
- for (Value *A :
- llvm::drop_begin(CB.args(), CB.getFunctionType()->getNumParams())) {
+ for (const auto &[ArgNo, A] : llvm::enumerate(CB.args())) {
----------------
vitalybuka wrote:
do we need to change the loop? drop_begin looks nicer
https://github.com/llvm/llvm-project/pull/109284
More information about the llvm-commits
mailing list