@@ -581,7 +581,8 @@ class MemorySanitizer {
581581 friend struct VarArgHelperBase ;
582582 friend struct VarArgAMD64Helper ;
583583 friend struct VarArgAArch64Helper ;
584- friend struct VarArgPowerPCHelper ;
584+ friend struct VarArgPowerPC64Helper ;
585+ friend struct VarArgPowerPC32Helper ;
585586 friend struct VarArgSystemZHelper ;
586587 friend struct VarArgI386Helper ;
587588 friend struct VarArgGenericHelper ;
@@ -6392,13 +6393,165 @@ struct VarArgAArch64Helper : public VarArgHelperBase {
63926393 }
63936394};
63946395
6395- // / PowerPC -specific implementation of VarArgHelper.
6396- struct VarArgPowerPCHelper : public VarArgHelperBase {
6396+ // / PowerPC64 -specific implementation of VarArgHelper.
6397+ struct VarArgPowerPC64Helper : public VarArgHelperBase {
63976398 AllocaInst *VAArgTLSCopy = nullptr ;
63986399 Value *VAArgSize = nullptr ;
63996400
6400- VarArgPowerPCHelper (Function &F, MemorySanitizer &MS,
6401- MemorySanitizerVisitor &MSV, unsigned VAListTagSize)
6401+ VarArgPowerPC64Helper (Function &F, MemorySanitizer &MS,
6402+ MemorySanitizerVisitor &MSV, unsigned VAListTagSize)
6403+ : VarArgHelperBase(F, MS, MSV, VAListTagSize) {}
6404+
6405+ void visitCallBase (CallBase &CB, IRBuilder<> &IRB) override {
6406+ // For PowerPC, we need to deal with alignment of stack arguments -
6407+ // they are mostly aligned to 8 bytes, but vectors and i128 arrays
6408+ // are aligned to 16 bytes, byvals can be aligned to 8 or 16 bytes,
6409+ // For that reason, we compute current offset from stack pointer (which is
6410+ // always properly aligned), and offset for the first vararg, then subtract
6411+ // them.
6412+ unsigned VAArgBase;
6413+ Triple TargetTriple (F.getParent ()->getTargetTriple ());
6414+ // Parameter save area starts at 48 bytes from frame pointer for ABIv1,
6415+ // and 32 bytes for ABIv2. This is usually determined by target
6416+ // endianness, but in theory could be overridden by function attribute.
6417+ if (TargetTriple.isPPC64 ()) {
6418+ if (TargetTriple.isPPC64ELFv2ABI ())
6419+ VAArgBase = 32 ;
6420+ else
6421+ VAArgBase = 48 ;
6422+ } else {
6423+ // Parameter save area is 8 bytes from frame pointer in PPC32
6424+ VAArgBase = 8 ;
6425+ }
6426+ unsigned VAArgOffset = VAArgBase;
6427+ const DataLayout &DL = F.getDataLayout ();
6428+ for (const auto &[ArgNo, A] : llvm::enumerate (CB.args ())) {
6429+ bool IsFixed = ArgNo < CB.getFunctionType ()->getNumParams ();
6430+ bool IsByVal = CB.paramHasAttr (ArgNo, Attribute::ByVal);
6431+ if (IsByVal) {
6432+ assert (A->getType ()->isPointerTy ());
6433+ Type *RealTy = CB.getParamByValType (ArgNo);
6434+ uint64_t ArgSize = DL.getTypeAllocSize (RealTy);
6435+ Align ArgAlign = CB.getParamAlign (ArgNo).value_or (Align (8 ));
6436+ if (ArgAlign < 8 )
6437+ ArgAlign = Align (8 );
6438+ VAArgOffset = alignTo (VAArgOffset, ArgAlign);
6439+ if (!IsFixed) {
6440+ Value *Base =
6441+ getShadowPtrForVAArgument (IRB, VAArgOffset - VAArgBase, ArgSize);
6442+ if (Base) {
6443+ Value *AShadowPtr, *AOriginPtr;
6444+ std::tie (AShadowPtr, AOriginPtr) =
6445+ MSV.getShadowOriginPtr (A, IRB, IRB.getInt8Ty (),
6446+ kShadowTLSAlignment , /* isStore*/ false );
6447+
6448+ IRB.CreateMemCpy (Base, kShadowTLSAlignment , AShadowPtr,
6449+ kShadowTLSAlignment , ArgSize);
6450+ }
6451+ }
6452+ VAArgOffset += alignTo (ArgSize, Align (8 ));
6453+ } else {
6454+ Value *Base;
6455+ uint64_t ArgSize = DL.getTypeAllocSize (A->getType ());
6456+ Align ArgAlign = Align (8 );
6457+ if (A->getType ()->isArrayTy ()) {
6458+ // Arrays are aligned to element size, except for long double
6459+ // arrays, which are aligned to 8 bytes.
6460+ Type *ElementTy = A->getType ()->getArrayElementType ();
6461+ if (!ElementTy->isPPC_FP128Ty ())
6462+ ArgAlign = Align (DL.getTypeAllocSize (ElementTy));
6463+ } else if (A->getType ()->isVectorTy ()) {
6464+ // Vectors are naturally aligned.
6465+ ArgAlign = Align (ArgSize);
6466+ }
6467+ if (ArgAlign < 8 )
6468+ ArgAlign = Align (8 );
6469+ VAArgOffset = alignTo (VAArgOffset, ArgAlign);
6470+ if (DL.isBigEndian ()) {
6471+ // Adjusting the shadow for argument with size < 8 to match the
6472+ // placement of bits in big endian system
6473+ if (ArgSize < 8 )
6474+ VAArgOffset += (8 - ArgSize);
6475+ }
6476+ if (!IsFixed) {
6477+ Base =
6478+ getShadowPtrForVAArgument (IRB, VAArgOffset - VAArgBase, ArgSize);
6479+ if (Base)
6480+ IRB.CreateAlignedStore (MSV.getShadow (A), Base, kShadowTLSAlignment );
6481+ }
6482+ VAArgOffset += ArgSize;
6483+ VAArgOffset = alignTo (VAArgOffset, Align (8 ));
6484+ }
6485+ if (IsFixed)
6486+ VAArgBase = VAArgOffset;
6487+ }
6488+
6489+ Constant *TotalVAArgSize =
6490+ ConstantInt::get (MS.IntptrTy , VAArgOffset - VAArgBase);
6491+ // Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of
6492+ // a new class member i.e. it is the total size of all VarArgs.
6493+ IRB.CreateStore (TotalVAArgSize, MS.VAArgOverflowSizeTLS );
6494+ }
6495+
6496+ void finalizeInstrumentation () override {
6497+ assert (!VAArgSize && !VAArgTLSCopy &&
6498+ " finalizeInstrumentation called twice" );
6499+ IRBuilder<> IRB (MSV.FnPrologueEnd );
6500+ VAArgSize = IRB.CreateLoad (IRB.getInt64Ty (), MS.VAArgOverflowSizeTLS );
6501+ Value *CopySize = VAArgSize;
6502+
6503+ if (!VAStartInstrumentationList.empty ()) {
6504+ // If there is a va_start in this function, make a backup copy of
6505+ // va_arg_tls somewhere in the function entry block.
6506+
6507+ VAArgTLSCopy = IRB.CreateAlloca (Type::getInt8Ty (*MS.C ), CopySize);
6508+ VAArgTLSCopy->setAlignment (kShadowTLSAlignment );
6509+ IRB.CreateMemSet (VAArgTLSCopy, Constant::getNullValue (IRB.getInt8Ty ()),
6510+ CopySize, kShadowTLSAlignment , false );
6511+
6512+ Value *SrcSize = IRB.CreateBinaryIntrinsic (
6513+ Intrinsic::umin, CopySize,
6514+ ConstantInt::get (IRB.getInt64Ty (), kParamTLSSize ));
6515+ IRB.CreateMemCpy (VAArgTLSCopy, kShadowTLSAlignment , MS.VAArgTLS ,
6516+ kShadowTLSAlignment , SrcSize);
6517+ }
6518+
6519+ // Instrument va_start.
6520+ // Copy va_list shadow from the backup copy of the TLS contents.
6521+ Triple TargetTriple (F.getParent ()->getTargetTriple ());
6522+ for (CallInst *OrigInst : VAStartInstrumentationList) {
6523+ NextNodeIRBuilder IRB (OrigInst);
6524+ Value *VAListTag = OrigInst->getArgOperand (0 );
6525+ Value *RegSaveAreaPtrPtr = IRB.CreatePtrToInt (VAListTag, MS.IntptrTy );
6526+
6527+ // In PPC32 va_list_tag is a struct, whereas in PPC64 it's a pointer
6528+ if (!TargetTriple.isPPC64 ()) {
6529+ RegSaveAreaPtrPtr =
6530+ IRB.CreateAdd (RegSaveAreaPtrPtr, ConstantInt::get (MS.IntptrTy , 8 ));
6531+ }
6532+ RegSaveAreaPtrPtr = IRB.CreateIntToPtr (RegSaveAreaPtrPtr, MS.PtrTy );
6533+
6534+ Value *RegSaveAreaPtr = IRB.CreateLoad (MS.PtrTy , RegSaveAreaPtrPtr);
6535+ Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
6536+ const DataLayout &DL = F.getDataLayout ();
6537+ unsigned IntptrSize = DL.getTypeStoreSize (MS.IntptrTy );
6538+ const Align Alignment = Align (IntptrSize);
6539+ std::tie (RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
6540+ MSV.getShadowOriginPtr (RegSaveAreaPtr, IRB, IRB.getInt8Ty (),
6541+ Alignment, /* isStore*/ true );
6542+ IRB.CreateMemCpy (RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
6543+ CopySize);
6544+ }
6545+ }
6546+ };
6547+
6548+ // / PowerPC32-specific implementation of VarArgHelper.
6549+ struct VarArgPowerPC32Helper : public VarArgHelperBase {
6550+ AllocaInst *VAArgTLSCopy = nullptr ;
6551+ Value *VAArgSize = nullptr ;
6552+
6553+ VarArgPowerPC32Helper (Function &F, MemorySanitizer &MS,
6554+ MemorySanitizerVisitor &MSV, unsigned VAListTagSize)
64026555 : VarArgHelperBase(F, MS, MSV, VAListTagSize) {}
64036556
64046557 void visitCallBase (CallBase &CB, IRBuilder<> &IRB) override {
@@ -7067,10 +7220,10 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,
70677220 // On PowerPC32 VAListTag is a struct
70687221 // {char, char, i16 padding, char *, char *}
70697222 if (TargetTriple.isPPC32 ())
7070- return new VarArgPowerPCHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 12 );
7223+ return new VarArgPowerPC32Helper (Func, Msan, Visitor, /* VAListTagSize=*/ 12 );
70717224
70727225 if (TargetTriple.isPPC64 ())
7073- return new VarArgPowerPCHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 8 );
7226+ return new VarArgPowerPC64Helper (Func, Msan, Visitor, /* VAListTagSize=*/ 8 );
70747227
70757228 if (TargetTriple.isRISCV32 ())
70767229 return new VarArgRISCVHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 4 );
0 commit comments