@@ -6399,8 +6399,8 @@ struct VarArgPowerPC64Helper : public VarArgHelperBase {
63996399 Value *VAArgSize = nullptr ;
64006400
64016401 VarArgPowerPC64Helper (Function &F, MemorySanitizer &MS,
6402- MemorySanitizerVisitor &MSV, unsigned VAListTagSize )
6403- : VarArgHelperBase(F, MS, MSV, VAListTagSize) {}
6402+ MemorySanitizerVisitor &MSV)
6403+ : VarArgHelperBase(F, MS, MSV, /* VAListTagSize= */ 8 ) {}
64046404
64056405 void visitCallBase (CallBase &CB, IRBuilder<> &IRB) override {
64066406 // For PowerPC, we need to deal with alignment of stack arguments -
@@ -6414,15 +6414,10 @@ struct VarArgPowerPC64Helper : public VarArgHelperBase {
64146414 // Parameter save area starts at 48 bytes from frame pointer for ABIv1,
64156415 // and 32 bytes for ABIv2. This is usually determined by target
64166416 // 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- }
6417+ if (TargetTriple.isPPC64ELFv2ABI ())
6418+ VAArgBase = 32 ;
6419+ else
6420+ VAArgBase = 48 ;
64266421 unsigned VAArgOffset = VAArgBase;
64276422 const DataLayout &DL = F.getDataLayout ();
64286423 for (const auto &[ArgNo, A] : llvm::enumerate (CB.args ())) {
@@ -6524,11 +6519,6 @@ struct VarArgPowerPC64Helper : public VarArgHelperBase {
65246519 Value *VAListTag = OrigInst->getArgOperand (0 );
65256520 Value *RegSaveAreaPtrPtr = IRB.CreatePtrToInt (VAListTag, MS.IntptrTy );
65266521
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- }
65326522 RegSaveAreaPtrPtr = IRB.CreateIntToPtr (RegSaveAreaPtrPtr, MS.PtrTy );
65336523
65346524 Value *RegSaveAreaPtr = IRB.CreateLoad (MS.PtrTy , RegSaveAreaPtrPtr);
@@ -6551,42 +6541,27 @@ struct VarArgPowerPC32Helper : public VarArgHelperBase {
65516541 Value *VAArgSize = nullptr ;
65526542
65536543 VarArgPowerPC32Helper (Function &F, MemorySanitizer &MS,
6554- MemorySanitizerVisitor &MSV, unsigned VAListTagSize )
6555- : VarArgHelperBase(F, MS, MSV, VAListTagSize) {}
6544+ MemorySanitizerVisitor &MSV)
6545+ : VarArgHelperBase(F, MS, MSV, /* VAListTagSize= */ 12 ) {}
65566546
65576547 void visitCallBase (CallBase &CB, IRBuilder<> &IRB) override {
6558- // For PowerPC, we need to deal with alignment of stack arguments -
6559- // they are mostly aligned to 8 bytes, but vectors and i128 arrays
6560- // are aligned to 16 bytes, byvals can be aligned to 8 or 16 bytes,
6561- // For that reason, we compute current offset from stack pointer (which is
6562- // always properly aligned), and offset for the first vararg, then subtract
6563- // them.
65646548 unsigned VAArgBase;
65656549 Triple TargetTriple (F.getParent ()->getTargetTriple ());
6566- // Parameter save area starts at 48 bytes from frame pointer for ABIv1,
6567- // and 32 bytes for ABIv2. This is usually determined by target
6568- // endianness, but in theory could be overridden by function attribute.
6569- if (TargetTriple.isPPC64 ()) {
6570- if (TargetTriple.isPPC64ELFv2ABI ())
6571- VAArgBase = 32 ;
6572- else
6573- VAArgBase = 48 ;
6574- } else {
6575- // Parameter save area is 8 bytes from frame pointer in PPC32
6576- VAArgBase = 8 ;
6577- }
6550+ // Parameter save area is 8 bytes from frame pointer in PPC32
6551+ VAArgBase = 8 ;
65786552 unsigned VAArgOffset = VAArgBase;
65796553 const DataLayout &DL = F.getDataLayout ();
6554+ unsigned IntptrSize = DL.getTypeStoreSize (IRB.getInt32Ty ());
65806555 for (const auto &[ArgNo, A] : llvm::enumerate (CB.args ())) {
65816556 bool IsFixed = ArgNo < CB.getFunctionType ()->getNumParams ();
65826557 bool IsByVal = CB.paramHasAttr (ArgNo, Attribute::ByVal);
65836558 if (IsByVal) {
65846559 assert (A->getType ()->isPointerTy ());
65856560 Type *RealTy = CB.getParamByValType (ArgNo);
65866561 uint64_t ArgSize = DL.getTypeAllocSize (RealTy);
6587- Align ArgAlign = CB.getParamAlign (ArgNo).value_or (Align (8 ));
6588- if (ArgAlign < 8 )
6589- ArgAlign = Align (8 );
6562+ Align ArgAlign = CB.getParamAlign (ArgNo).value_or (Align (IntptrSize ));
6563+ if (ArgAlign < IntptrSize )
6564+ ArgAlign = Align (IntptrSize );
65906565 VAArgOffset = alignTo (VAArgOffset, ArgAlign);
65916566 if (!IsFixed) {
65926567 Value *Base =
@@ -6601,45 +6576,51 @@ struct VarArgPowerPC32Helper : public VarArgHelperBase {
66016576 kShadowTLSAlignment , ArgSize);
66026577 }
66036578 }
6604- VAArgOffset += alignTo (ArgSize, Align (8 ));
6579+ VAArgOffset += alignTo (ArgSize, Align (IntptrSize ));
66056580 } else {
66066581 Value *Base;
6607- uint64_t ArgSize = DL.getTypeAllocSize (A->getType ());
6608- Align ArgAlign = Align (8 );
6609- if (A->getType ()->isArrayTy ()) {
6610- // Arrays are aligned to element size, except for long double
6611- // arrays, which are aligned to 8 bytes.
6612- Type *ElementTy = A->getType ()->getArrayElementType ();
6613- if (!ElementTy->isPPC_FP128Ty ())
6614- ArgAlign = Align (DL.getTypeAllocSize (ElementTy));
6615- } else if (A->getType ()->isVectorTy ()) {
6616- // Vectors are naturally aligned.
6617- ArgAlign = Align (ArgSize);
6618- }
6619- if (ArgAlign < 8 )
6620- ArgAlign = Align (8 );
6621- VAArgOffset = alignTo (VAArgOffset, ArgAlign);
6622- if (DL.isBigEndian ()) {
6623- // Adjusting the shadow for argument with size < 8 to match the
6624- // placement of bits in big endian system
6625- if (ArgSize < 8 )
6626- VAArgOffset += (8 - ArgSize);
6627- }
6628- if (!IsFixed) {
6629- Base =
6630- getShadowPtrForVAArgument (IRB, VAArgOffset - VAArgBase, ArgSize);
6631- if (Base)
6632- IRB.CreateAlignedStore (MSV.getShadow (A), Base, kShadowTLSAlignment );
6582+ Type *ArgTy = A->getType ();
6583+
6584+ // On PPC 32 floating point variable arguments are stored in separate
6585+ // area: fp_save_area = reg_save_area + 4*8. We do not copy shaodow for
6586+ // them as they will be found when checking call arguments.
6587+ if (!ArgTy->isFloatingPointTy ()) {
6588+ uint64_t ArgSize = DL.getTypeAllocSize (ArgTy);
6589+ Align ArgAlign = Align (IntptrSize);
6590+ if (ArgTy->isArrayTy ()) {
6591+ // Arrays are aligned to element size, except for long double
6592+ // arrays, which are aligned to 8 bytes.
6593+ Type *ElementTy = ArgTy->getArrayElementType ();
6594+ if (!ElementTy->isPPC_FP128Ty ())
6595+ ArgAlign = Align (DL.getTypeAllocSize (ElementTy));
6596+ } else if (ArgTy->isVectorTy ()) {
6597+ // Vectors are naturally aligned.
6598+ ArgAlign = Align (ArgSize);
6599+ }
6600+ if (ArgAlign < IntptrSize)
6601+ ArgAlign = Align (IntptrSize);
6602+ VAArgOffset = alignTo (VAArgOffset, ArgAlign);
6603+ if (DL.isBigEndian ()) {
6604+ // Adjusting the shadow for argument with size < IntptrSize to match
6605+ // the placement of bits in big endian system
6606+ if (ArgSize < IntptrSize)
6607+ VAArgOffset += (IntptrSize - ArgSize);
6608+ }
6609+ if (!IsFixed) {
6610+ Base = getShadowPtrForVAArgument (IRB, VAArgOffset - VAArgBase,
6611+ ArgSize);
6612+ if (Base)
6613+ IRB.CreateAlignedStore (MSV.getShadow (A), Base,
6614+ kShadowTLSAlignment );
6615+ }
6616+ VAArgOffset += ArgSize;
6617+ VAArgOffset = alignTo (VAArgOffset, Align (IntptrSize));
66336618 }
6634- VAArgOffset += ArgSize;
6635- VAArgOffset = alignTo (VAArgOffset, Align (8 ));
66366619 }
6637- if (IsFixed)
6638- VAArgBase = VAArgOffset;
66396620 }
66406621
66416622 Constant *TotalVAArgSize =
6642- ConstantInt::get (MS. IntptrTy , VAArgOffset - VAArgBase);
6623+ ConstantInt::get (IRB. getInt32Ty () , VAArgOffset - VAArgBase);
66436624 // Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of
66446625 // a new class member i.e. it is the total size of all VarArgs.
66456626 IRB.CreateStore (TotalVAArgSize, MS.VAArgOverflowSizeTLS );
@@ -6649,7 +6630,7 @@ struct VarArgPowerPC32Helper : public VarArgHelperBase {
66496630 assert (!VAArgSize && !VAArgTLSCopy &&
66506631 " finalizeInstrumentation called twice" );
66516632 IRBuilder<> IRB (MSV.FnPrologueEnd );
6652- VAArgSize = IRB.CreateLoad (MS. IntptrTy , MS.VAArgOverflowSizeTLS );
6633+ VAArgSize = IRB.CreateLoad (IRB. getInt32Ty () , MS.VAArgOverflowSizeTLS );
66536634 Value *CopySize = VAArgSize;
66546635
66556636 if (!VAStartInstrumentationList.empty ()) {
@@ -6663,7 +6644,7 @@ struct VarArgPowerPC32Helper : public VarArgHelperBase {
66636644
66646645 Value *SrcSize = IRB.CreateBinaryIntrinsic (
66656646 Intrinsic::umin, CopySize,
6666- ConstantInt::get (MS. IntptrTy , kParamTLSSize ));
6647+ ConstantInt::get (IRB. getInt32Ty () , kParamTLSSize ));
66676648 IRB.CreateMemCpy (VAArgTLSCopy, kShadowTLSAlignment , MS.VAArgTLS ,
66686649 kShadowTLSAlignment , SrcSize);
66696650 }
@@ -6674,25 +6655,71 @@ struct VarArgPowerPC32Helper : public VarArgHelperBase {
66746655 for (CallInst *OrigInst : VAStartInstrumentationList) {
66756656 NextNodeIRBuilder IRB (OrigInst);
66766657 Value *VAListTag = OrigInst->getArgOperand (0 );
6677- Value *RegSaveAreaPtrPtr = IRB.CreatePtrToInt (VAListTag, MS.IntptrTy );
6658+ Value *RegSaveAreaPtrPtr =
6659+ IRB.CreatePtrToInt (VAListTag, IRB.getInt32Ty ());
6660+ Value *RegSaveAreaSize = CopySize;
66786661
6679- // In PPC32 va_list_tag is a struct, whereas in PPC64 it's a pointer
6680- if (!TargetTriple.isPPC64 ()) {
6681- RegSaveAreaPtrPtr =
6682- IRB.CreateAdd (RegSaveAreaPtrPtr, ConstantInt::get (MS.IntptrTy , 8 ));
6683- }
6684- RegSaveAreaPtrPtr = IRB.CreateIntToPtr (RegSaveAreaPtrPtr, MS.PtrTy );
6662+ // In PPC32 va_list_tag is a struct
6663+ RegSaveAreaPtrPtr = IRB.CreateAdd (RegSaveAreaPtrPtr,
6664+ ConstantInt::get (IRB.getInt32Ty (), 8 ));
66856665
6666+ // On PPC 32 reg_save_area can only hold 32 bytes of data
6667+ RegSaveAreaSize = IRB.CreateBinaryIntrinsic (
6668+ Intrinsic::umin, CopySize, ConstantInt::get (IRB.getInt32Ty (), 32 ));
6669+
6670+ RegSaveAreaPtrPtr = IRB.CreateIntToPtr (RegSaveAreaPtrPtr, MS.PtrTy );
66866671 Value *RegSaveAreaPtr = IRB.CreateLoad (MS.PtrTy , RegSaveAreaPtrPtr);
6687- Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
6672+
66886673 const DataLayout &DL = F.getDataLayout ();
6689- unsigned IntptrSize = DL.getTypeStoreSize (MS. IntptrTy );
6674+ unsigned IntptrSize = DL.getTypeStoreSize (IRB. getInt32Ty () );
66906675 const Align Alignment = Align (IntptrSize);
6691- std::tie (RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
6692- MSV.getShadowOriginPtr (RegSaveAreaPtr, IRB, IRB.getInt8Ty (),
6693- Alignment, /* isStore*/ true );
6694- IRB.CreateMemCpy (RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
6695- CopySize);
6676+
6677+ { // Copy reg save area
6678+ Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
6679+ std::tie (RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
6680+ MSV.getShadowOriginPtr (RegSaveAreaPtr, IRB, IRB.getInt8Ty (),
6681+ Alignment, /* isStore*/ true );
6682+ IRB.CreateMemCpy (RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy,
6683+ Alignment, RegSaveAreaSize);
6684+
6685+ RegSaveAreaShadowPtr =
6686+ IRB.CreatePtrToInt (RegSaveAreaShadowPtr, IRB.getInt32Ty ());
6687+ Value *FPSaveArea = IRB.CreateAdd (
6688+ RegSaveAreaShadowPtr, ConstantInt::get (IRB.getInt32Ty (), 32 ));
6689+ FPSaveArea = IRB.CreateIntToPtr (FPSaveArea, MS.PtrTy );
6690+ // We fill fp shadow with zeroes as uninitialized fp args should have
6691+ // been found during call base check
6692+ IRB.CreateMemSet (FPSaveArea, ConstantInt::getNullValue (IRB.getInt8Ty ()),
6693+ ConstantInt::get (IRB.getInt32Ty (), 32 ), Alignment);
6694+ }
6695+
6696+ { // Copy overflow area
6697+ // RegSaveAreaSize is min(CopySize, 32) -> no overflow can occur
6698+ Value *OverflowAreaSize = IRB.CreateSub (CopySize, RegSaveAreaSize);
6699+
6700+ Value *OverflowAreaPtrPtr =
6701+ IRB.CreatePtrToInt (VAListTag, IRB.getInt32Ty ());
6702+ OverflowAreaPtrPtr = IRB.CreateAdd (
6703+ OverflowAreaPtrPtr, ConstantInt::get (IRB.getInt32Ty (), 4 ));
6704+ OverflowAreaPtrPtr = IRB.CreateIntToPtr (OverflowAreaPtrPtr, MS.PtrTy );
6705+
6706+ Value *OverflowAreaPtr = IRB.CreateLoad (MS.PtrTy , OverflowAreaPtrPtr);
6707+
6708+ Value *OverflowAreaShadowPtr, *OverflowAreaOriginPtr;
6709+ std::tie (OverflowAreaShadowPtr, OverflowAreaOriginPtr) =
6710+ MSV.getShadowOriginPtr (OverflowAreaPtr, IRB, IRB.getInt8Ty (),
6711+ Alignment, /* isStore*/ true );
6712+
6713+ Value *OverflowVAArgTLSCopyPtr =
6714+ IRB.CreatePtrToInt (VAArgTLSCopy, IRB.getInt32Ty ());
6715+ OverflowVAArgTLSCopyPtr =
6716+ IRB.CreateAdd (OverflowVAArgTLSCopyPtr, RegSaveAreaSize);
6717+
6718+ OverflowVAArgTLSCopyPtr =
6719+ IRB.CreateIntToPtr (OverflowVAArgTLSCopyPtr, MS.PtrTy );
6720+ IRB.CreateMemCpy (OverflowAreaShadowPtr, Alignment,
6721+ OverflowVAArgTLSCopyPtr, Alignment, OverflowAreaSize);
6722+ }
66966723 }
66976724 }
66986725};
@@ -7220,10 +7247,10 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,
72207247 // On PowerPC32 VAListTag is a struct
72217248 // {char, char, i16 padding, char *, char *}
72227249 if (TargetTriple.isPPC32 ())
7223- return new VarArgPowerPC32Helper (Func, Msan, Visitor, /* VAListTagSize= */ 12 );
7250+ return new VarArgPowerPC32Helper (Func, Msan, Visitor);
72247251
72257252 if (TargetTriple.isPPC64 ())
7226- return new VarArgPowerPC64Helper (Func, Msan, Visitor, /* VAListTagSize= */ 8 );
7253+ return new VarArgPowerPC64Helper (Func, Msan, Visitor);
72277254
72287255 if (TargetTriple.isRISCV32 ())
72297256 return new VarArgRISCVHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 4 );
0 commit comments