@@ -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 (MS.IntptrTy );
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,41 +6576,47 @@ 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 =
@@ -6675,24 +6656,68 @@ struct VarArgPowerPC32Helper : public VarArgHelperBase {
66756656 NextNodeIRBuilder IRB (OrigInst);
66766657 Value *VAListTag = OrigInst->getArgOperand (0 );
66776658 Value *RegSaveAreaPtrPtr = IRB.CreatePtrToInt (VAListTag, MS.IntptrTy );
6659+ Value *RegSaveAreaSize = CopySize;
66786660
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 );
6661+ // In PPC32 va_list_tag is a struct
6662+ RegSaveAreaPtrPtr =
6663+ IRB.CreateAdd (RegSaveAreaPtrPtr, ConstantInt::get (MS.IntptrTy , 8 ));
6664+
6665+ // On PPC 32 reg_save_area can only hold 32 bytes of data
6666+ RegSaveAreaSize = IRB.CreateBinaryIntrinsic (
6667+ Intrinsic::umin, CopySize, ConstantInt::get (MS.IntptrTy , 32 ));
66856668
6669+ RegSaveAreaPtrPtr = IRB.CreateIntToPtr (RegSaveAreaPtrPtr, MS.PtrTy );
66866670 Value *RegSaveAreaPtr = IRB.CreateLoad (MS.PtrTy , RegSaveAreaPtrPtr);
6687- Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
6671+
66886672 const DataLayout &DL = F.getDataLayout ();
66896673 unsigned IntptrSize = DL.getTypeStoreSize (MS.IntptrTy );
66906674 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);
6675+
6676+ { // Copy reg save area
6677+ Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
6678+ std::tie (RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
6679+ MSV.getShadowOriginPtr (RegSaveAreaPtr, IRB, IRB.getInt8Ty (),
6680+ Alignment, /* isStore*/ true );
6681+ IRB.CreateMemCpy (RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy,
6682+ Alignment, RegSaveAreaSize);
6683+
6684+ RegSaveAreaShadowPtr =
6685+ IRB.CreatePtrToInt (RegSaveAreaShadowPtr, MS.IntptrTy );
6686+ Value *FPSaveArea = IRB.CreateAdd (RegSaveAreaShadowPtr,
6687+ ConstantInt::get (MS.IntptrTy , 32 ));
6688+ FPSaveArea = IRB.CreateIntToPtr (FPSaveArea, MS.PtrTy );
6689+ // We fill fp shadow with zeroes as uninitialized fp args should have
6690+ // been found during call base check
6691+ IRB.CreateMemSet (FPSaveArea, ConstantInt::getNullValue (IRB.getInt8Ty ()),
6692+ ConstantInt::get (MS.IntptrTy , 32 ), Alignment);
6693+ }
6694+
6695+ { // Copy overflow area
6696+ // RegSaveAreaSize is min(CopySize, 32) -> no overflow can occur
6697+ Value *OverflowAreaSize = IRB.CreateSub (CopySize, RegSaveAreaSize);
6698+
6699+ Value *OverflowAreaPtrPtr = IRB.CreatePtrToInt (VAListTag, MS.IntptrTy );
6700+ OverflowAreaPtrPtr =
6701+ IRB.CreateAdd (OverflowAreaPtrPtr, ConstantInt::get (MS.IntptrTy , 4 ));
6702+ OverflowAreaPtrPtr = IRB.CreateIntToPtr (OverflowAreaPtrPtr, MS.PtrTy );
6703+
6704+ Value *OverflowAreaPtr = IRB.CreateLoad (MS.PtrTy , OverflowAreaPtrPtr);
6705+
6706+ Value *OverflowAreaShadowPtr, *OverflowAreaOriginPtr;
6707+ std::tie (OverflowAreaShadowPtr, OverflowAreaOriginPtr) =
6708+ MSV.getShadowOriginPtr (OverflowAreaPtr, IRB, IRB.getInt8Ty (),
6709+ Alignment, /* isStore*/ true );
6710+
6711+ Value *OverflowVAArgTLSCopyPtr =
6712+ IRB.CreatePtrToInt (VAArgTLSCopy, MS.IntptrTy );
6713+ OverflowVAArgTLSCopyPtr =
6714+ IRB.CreateAdd (OverflowVAArgTLSCopyPtr, RegSaveAreaSize);
6715+
6716+ OverflowVAArgTLSCopyPtr =
6717+ IRB.CreateIntToPtr (OverflowVAArgTLSCopyPtr, MS.PtrTy );
6718+ IRB.CreateMemCpy (OverflowAreaShadowPtr, Alignment,
6719+ OverflowVAArgTLSCopyPtr, Alignment, OverflowAreaSize);
6720+ }
66966721 }
66976722 }
66986723};
@@ -7220,10 +7245,10 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,
72207245 // On PowerPC32 VAListTag is a struct
72217246 // {char, char, i16 padding, char *, char *}
72227247 if (TargetTriple.isPPC32 ())
7223- return new VarArgPowerPC32Helper (Func, Msan, Visitor, /* VAListTagSize= */ 12 );
7248+ return new VarArgPowerPC32Helper (Func, Msan, Visitor);
72247249
72257250 if (TargetTriple.isPPC64 ())
7226- return new VarArgPowerPC64Helper (Func, Msan, Visitor, /* VAListTagSize= */ 8 );
7251+ return new VarArgPowerPC64Helper (Func, Msan, Visitor);
72277252
72287253 if (TargetTriple.isRISCV32 ())
72297254 return new VarArgRISCVHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 4 );
0 commit comments