@@ -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 ;
@@ -6271,12 +6272,164 @@ struct VarArgAArch64Helper : public VarArgHelperBase {
62716272 }
62726273};
62736274
6274- // / PowerPC -specific implementation of VarArgHelper.
6275- struct VarArgPowerPCHelper : public VarArgHelperBase {
6275+ // / PowerPC64 -specific implementation of VarArgHelper.
6276+ struct VarArgPowerPC64Helper : public VarArgHelperBase {
62766277 AllocaInst *VAArgTLSCopy = nullptr ;
62776278 Value *VAArgSize = nullptr ;
62786279
6279- VarArgPowerPCHelper (Function &F, MemorySanitizer &MS,
6280+ VarArgPowerPC64Helper (Function &F, MemorySanitizer &MS,
6281+ MemorySanitizerVisitor &MSV, unsigned VAListTagSize)
6282+ : VarArgHelperBase(F, MS, MSV, VAListTagSize) {}
6283+
6284+ void visitCallBase (CallBase &CB, IRBuilder<> &IRB) override {
6285+ // For PowerPC, we need to deal with alignment of stack arguments -
6286+ // they are mostly aligned to 8 bytes, but vectors and i128 arrays
6287+ // are aligned to 16 bytes, byvals can be aligned to 8 or 16 bytes,
6288+ // For that reason, we compute current offset from stack pointer (which is
6289+ // always properly aligned), and offset for the first vararg, then subtract
6290+ // them.
6291+ unsigned VAArgBase;
6292+ Triple TargetTriple (F.getParent ()->getTargetTriple ());
6293+ // Parameter save area starts at 48 bytes from frame pointer for ABIv1,
6294+ // and 32 bytes for ABIv2. This is usually determined by target
6295+ // endianness, but in theory could be overridden by function attribute.
6296+ if (TargetTriple.isPPC64 ()) {
6297+ if (TargetTriple.isPPC64ELFv2ABI ())
6298+ VAArgBase = 32 ;
6299+ else
6300+ VAArgBase = 48 ;
6301+ } else {
6302+ // Parameter save area is 8 bytes from frame pointer in PPC32
6303+ VAArgBase = 8 ;
6304+ }
6305+ unsigned VAArgOffset = VAArgBase;
6306+ const DataLayout &DL = F.getDataLayout ();
6307+ for (const auto &[ArgNo, A] : llvm::enumerate (CB.args ())) {
6308+ bool IsFixed = ArgNo < CB.getFunctionType ()->getNumParams ();
6309+ bool IsByVal = CB.paramHasAttr (ArgNo, Attribute::ByVal);
6310+ if (IsByVal) {
6311+ assert (A->getType ()->isPointerTy ());
6312+ Type *RealTy = CB.getParamByValType (ArgNo);
6313+ uint64_t ArgSize = DL.getTypeAllocSize (RealTy);
6314+ Align ArgAlign = CB.getParamAlign (ArgNo).value_or (Align (8 ));
6315+ if (ArgAlign < 8 )
6316+ ArgAlign = Align (8 );
6317+ VAArgOffset = alignTo (VAArgOffset, ArgAlign);
6318+ if (!IsFixed) {
6319+ Value *Base =
6320+ getShadowPtrForVAArgument (IRB, VAArgOffset - VAArgBase, ArgSize);
6321+ if (Base) {
6322+ Value *AShadowPtr, *AOriginPtr;
6323+ std::tie (AShadowPtr, AOriginPtr) =
6324+ MSV.getShadowOriginPtr (A, IRB, IRB.getInt8Ty (),
6325+ kShadowTLSAlignment , /* isStore*/ false );
6326+
6327+ IRB.CreateMemCpy (Base, kShadowTLSAlignment , AShadowPtr,
6328+ kShadowTLSAlignment , ArgSize);
6329+ }
6330+ }
6331+ VAArgOffset += alignTo (ArgSize, Align (8 ));
6332+ } else {
6333+ Value *Base;
6334+ uint64_t ArgSize = DL.getTypeAllocSize (A->getType ());
6335+ Align ArgAlign = Align (8 );
6336+ if (A->getType ()->isArrayTy ()) {
6337+ // Arrays are aligned to element size, except for long double
6338+ // arrays, which are aligned to 8 bytes.
6339+ Type *ElementTy = A->getType ()->getArrayElementType ();
6340+ if (!ElementTy->isPPC_FP128Ty ())
6341+ ArgAlign = Align (DL.getTypeAllocSize (ElementTy));
6342+ } else if (A->getType ()->isVectorTy ()) {
6343+ // Vectors are naturally aligned.
6344+ ArgAlign = Align (ArgSize);
6345+ }
6346+ if (ArgAlign < 8 )
6347+ ArgAlign = Align (8 );
6348+ VAArgOffset = alignTo (VAArgOffset, ArgAlign);
6349+ if (DL.isBigEndian ()) {
6350+ // Adjusting the shadow for argument with size < 8 to match the
6351+ // placement of bits in big endian system
6352+ if (ArgSize < 8 )
6353+ VAArgOffset += (8 - ArgSize);
6354+ }
6355+ if (!IsFixed) {
6356+ Base =
6357+ getShadowPtrForVAArgument (IRB, VAArgOffset - VAArgBase, ArgSize);
6358+ if (Base)
6359+ IRB.CreateAlignedStore (MSV.getShadow (A), Base, kShadowTLSAlignment );
6360+ }
6361+ VAArgOffset += ArgSize;
6362+ VAArgOffset = alignTo (VAArgOffset, Align (8 ));
6363+ }
6364+ if (IsFixed)
6365+ VAArgBase = VAArgOffset;
6366+ }
6367+
6368+ Constant *TotalVAArgSize =
6369+ ConstantInt::get (MS.IntptrTy , VAArgOffset - VAArgBase);
6370+ // Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of
6371+ // a new class member i.e. it is the total size of all VarArgs.
6372+ IRB.CreateStore (TotalVAArgSize, MS.VAArgOverflowSizeTLS );
6373+ }
6374+
6375+ void finalizeInstrumentation () override {
6376+ assert (!VAArgSize && !VAArgTLSCopy &&
6377+ " finalizeInstrumentation called twice" );
6378+ IRBuilder<> IRB (MSV.FnPrologueEnd );
6379+ VAArgSize = IRB.CreateLoad (IRB.getInt64Ty (), MS.VAArgOverflowSizeTLS );
6380+ Value *CopySize = VAArgSize;
6381+
6382+ if (!VAStartInstrumentationList.empty ()) {
6383+ // If there is a va_start in this function, make a backup copy of
6384+ // va_arg_tls somewhere in the function entry block.
6385+
6386+ VAArgTLSCopy = IRB.CreateAlloca (Type::getInt8Ty (*MS.C ), CopySize);
6387+ VAArgTLSCopy->setAlignment (kShadowTLSAlignment );
6388+ IRB.CreateMemSet (VAArgTLSCopy, Constant::getNullValue (IRB.getInt8Ty ()),
6389+ CopySize, kShadowTLSAlignment , false );
6390+
6391+ Value *SrcSize = IRB.CreateBinaryIntrinsic (
6392+ Intrinsic::umin, CopySize,
6393+ ConstantInt::get (IRB.getInt64Ty (), kParamTLSSize ));
6394+ IRB.CreateMemCpy (VAArgTLSCopy, kShadowTLSAlignment , MS.VAArgTLS ,
6395+ kShadowTLSAlignment , SrcSize);
6396+ }
6397+
6398+ // Instrument va_start.
6399+ // Copy va_list shadow from the backup copy of the TLS contents.
6400+ Triple TargetTriple (F.getParent ()->getTargetTriple ());
6401+ for (CallInst *OrigInst : VAStartInstrumentationList) {
6402+ NextNodeIRBuilder IRB (OrigInst);
6403+ Value *VAListTag = OrigInst->getArgOperand (0 );
6404+ Value *RegSaveAreaPtrPtr = IRB.CreatePtrToInt (VAListTag, MS.IntptrTy );
6405+
6406+ // In PPC32 va_list_tag is a struct, whereas in PPC64 it's a pointer
6407+ if (!TargetTriple.isPPC64 ()) {
6408+ RegSaveAreaPtrPtr =
6409+ IRB.CreateAdd (RegSaveAreaPtrPtr, ConstantInt::get (MS.IntptrTy , 8 ));
6410+ }
6411+ RegSaveAreaPtrPtr = IRB.CreateIntToPtr (RegSaveAreaPtrPtr, MS.PtrTy );
6412+
6413+ Value *RegSaveAreaPtr = IRB.CreateLoad (MS.PtrTy , RegSaveAreaPtrPtr);
6414+ Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
6415+ const DataLayout &DL = F.getDataLayout ();
6416+ unsigned IntptrSize = DL.getTypeStoreSize (MS.IntptrTy );
6417+ const Align Alignment = Align (IntptrSize);
6418+ std::tie (RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
6419+ MSV.getShadowOriginPtr (RegSaveAreaPtr, IRB, IRB.getInt8Ty (),
6420+ Alignment, /* isStore*/ true );
6421+ IRB.CreateMemCpy (RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
6422+ CopySize);
6423+ }
6424+ }
6425+ };
6426+
6427+ // / PowerPC32-specific implementation of VarArgHelper.
6428+ struct VarArgPowerPC32Helper : public VarArgHelperBase {
6429+ AllocaInst *VAArgTLSCopy = nullptr ;
6430+ Value *VAArgSize = nullptr ;
6431+
6432+ VarArgPowerPC32Helper (Function &F, MemorySanitizer &MS,
62806433 MemorySanitizerVisitor &MSV, unsigned VAListTagSize)
62816434 : VarArgHelperBase(F, MS, MSV, VAListTagSize) {}
62826435
@@ -6946,10 +7099,10 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,
69467099 // On PowerPC32 VAListTag is a struct
69477100 // {char, char, i16 padding, char *, char *}
69487101 if (TargetTriple.isPPC32 ())
6949- return new VarArgPowerPCHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 12 );
7102+ return new VarArgPowerPC32Helper (Func, Msan, Visitor, /* VAListTagSize=*/ 12 );
69507103
69517104 if (TargetTriple.isPPC64 ())
6952- return new VarArgPowerPCHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 8 );
7105+ return new VarArgPowerPC64Helper (Func, Msan, Visitor, /* VAListTagSize=*/ 8 );
69537106
69547107 if (TargetTriple.isRISCV32 ())
69557108 return new VarArgRISCVHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 4 );
0 commit comments