[llvm] [nfc][Msan] Split PPC VarArg Helper into PPC32 and PPC64 (PR #134860)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 8 07:21:11 PDT 2025
https://github.com/k-kashapov created https://github.com/llvm/llvm-project/pull/134860
As discussed in https://github.com/llvm/llvm-project/pull/131827, copied ppc32 helper from ppc64. No functional changes have been made.
Ping @vitalybuka, @EugeneZelenko
>From 1fc6217d51e8a336fc7cc013c6b5dc9e91207da1 Mon Sep 17 00:00:00 2001
From: Kamil Kashapov <kashapov at ispras.ru>
Date: Tue, 8 Apr 2025 17:18:28 +0300
Subject: [PATCH] Split PPC VarArg Helper into PPC32 and PPC64
---
.../Instrumentation/MemorySanitizer.cpp | 165 +++++++++++++++++-
1 file changed, 159 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 49c8d384dfe73..c46de3afa3bf0 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -581,7 +581,8 @@ class MemorySanitizer {
friend struct VarArgHelperBase;
friend struct VarArgAMD64Helper;
friend struct VarArgAArch64Helper;
- friend struct VarArgPowerPCHelper;
+ friend struct VarArgPowerPC64Helper;
+ friend struct VarArgPowerPC32Helper;
friend struct VarArgSystemZHelper;
friend struct VarArgI386Helper;
friend struct VarArgGenericHelper;
@@ -6271,12 +6272,164 @@ struct VarArgAArch64Helper : public VarArgHelperBase {
}
};
-/// PowerPC-specific implementation of VarArgHelper.
-struct VarArgPowerPCHelper : public VarArgHelperBase {
+/// PowerPC64-specific implementation of VarArgHelper.
+struct VarArgPowerPC64Helper : public VarArgHelperBase {
AllocaInst *VAArgTLSCopy = nullptr;
Value *VAArgSize = nullptr;
- VarArgPowerPCHelper(Function &F, MemorySanitizer &MS,
+ VarArgPowerPC64Helper(Function &F, MemorySanitizer &MS,
+ MemorySanitizerVisitor &MSV, unsigned VAListTagSize)
+ : VarArgHelperBase(F, MS, MSV, VAListTagSize) {}
+
+ void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {
+ // For PowerPC, we need to deal with alignment of stack arguments -
+ // they are mostly aligned to 8 bytes, but vectors and i128 arrays
+ // are aligned to 16 bytes, byvals can be aligned to 8 or 16 bytes,
+ // For that reason, we compute current offset from stack pointer (which is
+ // always properly aligned), and offset for the first vararg, then subtract
+ // them.
+ unsigned VAArgBase;
+ Triple TargetTriple(F.getParent()->getTargetTriple());
+ // Parameter save area starts at 48 bytes from frame pointer for ABIv1,
+ // and 32 bytes for ABIv2. This is usually determined by target
+ // endianness, but in theory could be overridden by function attribute.
+ if (TargetTriple.isPPC64()) {
+ if (TargetTriple.isPPC64ELFv2ABI())
+ VAArgBase = 32;
+ else
+ VAArgBase = 48;
+ } else {
+ // Parameter save area is 8 bytes from frame pointer in PPC32
+ VAArgBase = 8;
+ }
+ unsigned VAArgOffset = VAArgBase;
+ const DataLayout &DL = F.getDataLayout();
+ 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(8));
+ if (ArgAlign < 8)
+ ArgAlign = Align(8);
+ VAArgOffset = alignTo(VAArgOffset, ArgAlign);
+ if (!IsFixed) {
+ Value *Base =
+ getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, 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(8));
+ } else {
+ Value *Base;
+ uint64_t ArgSize = DL.getTypeAllocSize(A->getType());
+ Align ArgAlign = Align(8);
+ if (A->getType()->isArrayTy()) {
+ // Arrays are aligned to element size, except for long double
+ // arrays, which are aligned to 8 bytes.
+ Type *ElementTy = A->getType()->getArrayElementType();
+ if (!ElementTy->isPPC_FP128Ty())
+ ArgAlign = Align(DL.getTypeAllocSize(ElementTy));
+ } else if (A->getType()->isVectorTy()) {
+ // Vectors are naturally aligned.
+ ArgAlign = Align(ArgSize);
+ }
+ if (ArgAlign < 8)
+ ArgAlign = Align(8);
+ VAArgOffset = alignTo(VAArgOffset, ArgAlign);
+ if (DL.isBigEndian()) {
+ // Adjusting the shadow for argument with size < 8 to match the
+ // placement of bits in big endian system
+ if (ArgSize < 8)
+ VAArgOffset += (8 - ArgSize);
+ }
+ if (!IsFixed) {
+ Base =
+ getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
+ if (Base)
+ IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment);
+ }
+ VAArgOffset += ArgSize;
+ VAArgOffset = alignTo(VAArgOffset, Align(8));
+ }
+ if (IsFixed)
+ VAArgBase = VAArgOffset;
+ }
+
+ Constant *TotalVAArgSize =
+ ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
+ // 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 = VAArgSize;
+
+ 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(IRB.getInt64Ty(), kParamTLSSize));
+ IRB.CreateMemCpy(VAArgTLSCopy, kShadowTLSAlignment, MS.VAArgTLS,
+ kShadowTLSAlignment, SrcSize);
+ }
+
+ // Instrument va_start.
+ // Copy va_list shadow from the backup copy of the TLS contents.
+ Triple TargetTriple(F.getParent()->getTargetTriple());
+ for (CallInst *OrigInst : VAStartInstrumentationList) {
+ NextNodeIRBuilder IRB(OrigInst);
+ Value *VAListTag = OrigInst->getArgOperand(0);
+ Value *RegSaveAreaPtrPtr = IRB.CreatePtrToInt(VAListTag, MS.IntptrTy);
+
+ // In PPC32 va_list_tag is a struct, whereas in PPC64 it's a pointer
+ if (!TargetTriple.isPPC64()) {
+ RegSaveAreaPtrPtr =
+ IRB.CreateAdd(RegSaveAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 8));
+ }
+ RegSaveAreaPtrPtr = IRB.CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
+
+ Value *RegSaveAreaPtr = IRB.CreateLoad(MS.PtrTy, RegSaveAreaPtrPtr);
+ Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
+ const DataLayout &DL = F.getDataLayout();
+ unsigned IntptrSize = DL.getTypeStoreSize(MS.IntptrTy);
+ 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);
+ }
+ }
+};
+
+/// PowerPC32-specific implementation of VarArgHelper.
+struct VarArgPowerPC32Helper : public VarArgHelperBase {
+ AllocaInst *VAArgTLSCopy = nullptr;
+ Value *VAArgSize = nullptr;
+
+ VarArgPowerPC32Helper(Function &F, MemorySanitizer &MS,
MemorySanitizerVisitor &MSV, unsigned VAListTagSize)
: VarArgHelperBase(F, MS, MSV, VAListTagSize) {}
@@ -6946,10 +7099,10 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,
// On PowerPC32 VAListTag is a struct
// {char, char, i16 padding, char *, char *}
if (TargetTriple.isPPC32())
- return new VarArgPowerPCHelper(Func, Msan, Visitor, /*VAListTagSize=*/12);
+ return new VarArgPowerPC32Helper(Func, Msan, Visitor, /*VAListTagSize=*/12);
if (TargetTriple.isPPC64())
- return new VarArgPowerPCHelper(Func, Msan, Visitor, /*VAListTagSize=*/8);
+ return new VarArgPowerPC64Helper(Func, Msan, Visitor, /*VAListTagSize=*/8);
if (TargetTriple.isRISCV32())
return new VarArgRISCVHelper(Func, Msan, Visitor, /*VAListTagSize=*/4);
More information about the llvm-commits
mailing list