@@ -6399,8 +6399,8 @@ struct VarArgPowerPC64Helper : public VarArgHelperBase {
6399
6399
Value *VAArgSize = nullptr ;
6400
6400
6401
6401
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 ) {}
6404
6404
6405
6405
void visitCallBase (CallBase &CB, IRBuilder<> &IRB) override {
6406
6406
// For PowerPC, we need to deal with alignment of stack arguments -
@@ -6414,15 +6414,10 @@ struct VarArgPowerPC64Helper : public VarArgHelperBase {
6414
6414
// Parameter save area starts at 48 bytes from frame pointer for ABIv1,
6415
6415
// and 32 bytes for ABIv2. This is usually determined by target
6416
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
- }
6417
+ if (TargetTriple.isPPC64ELFv2ABI ())
6418
+ VAArgBase = 32 ;
6419
+ else
6420
+ VAArgBase = 48 ;
6426
6421
unsigned VAArgOffset = VAArgBase;
6427
6422
const DataLayout &DL = F.getDataLayout ();
6428
6423
for (const auto &[ArgNo, A] : llvm::enumerate (CB.args ())) {
@@ -6524,11 +6519,6 @@ struct VarArgPowerPC64Helper : public VarArgHelperBase {
6524
6519
Value *VAListTag = OrigInst->getArgOperand (0 );
6525
6520
Value *RegSaveAreaPtrPtr = IRB.CreatePtrToInt (VAListTag, MS.IntptrTy );
6526
6521
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
6522
RegSaveAreaPtrPtr = IRB.CreateIntToPtr (RegSaveAreaPtrPtr, MS.PtrTy );
6533
6523
6534
6524
Value *RegSaveAreaPtr = IRB.CreateLoad (MS.PtrTy , RegSaveAreaPtrPtr);
@@ -6551,42 +6541,27 @@ struct VarArgPowerPC32Helper : public VarArgHelperBase {
6551
6541
Value *VAArgSize = nullptr ;
6552
6542
6553
6543
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 ) {}
6556
6546
6557
6547
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.
6564
6548
unsigned VAArgBase;
6565
6549
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 ;
6578
6552
unsigned VAArgOffset = VAArgBase;
6579
6553
const DataLayout &DL = F.getDataLayout ();
6554
+ unsigned IntptrSize = DL.getTypeStoreSize (IRB.getInt32Ty ());
6580
6555
for (const auto &[ArgNo, A] : llvm::enumerate (CB.args ())) {
6581
6556
bool IsFixed = ArgNo < CB.getFunctionType ()->getNumParams ();
6582
6557
bool IsByVal = CB.paramHasAttr (ArgNo, Attribute::ByVal);
6583
6558
if (IsByVal) {
6584
6559
assert (A->getType ()->isPointerTy ());
6585
6560
Type *RealTy = CB.getParamByValType (ArgNo);
6586
6561
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 );
6590
6565
VAArgOffset = alignTo (VAArgOffset, ArgAlign);
6591
6566
if (!IsFixed) {
6592
6567
Value *Base =
@@ -6601,45 +6576,51 @@ struct VarArgPowerPC32Helper : public VarArgHelperBase {
6601
6576
kShadowTLSAlignment , ArgSize);
6602
6577
}
6603
6578
}
6604
- VAArgOffset += alignTo (ArgSize, Align (8 ));
6579
+ VAArgOffset += alignTo (ArgSize, Align (IntptrSize ));
6605
6580
} else {
6606
6581
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));
6633
6618
}
6634
- VAArgOffset += ArgSize;
6635
- VAArgOffset = alignTo (VAArgOffset, Align (8 ));
6636
6619
}
6637
- if (IsFixed)
6638
- VAArgBase = VAArgOffset;
6639
6620
}
6640
6621
6641
6622
Constant *TotalVAArgSize =
6642
- ConstantInt::get (MS. IntptrTy , VAArgOffset - VAArgBase);
6623
+ ConstantInt::get (IRB. getInt32Ty () , VAArgOffset - VAArgBase);
6643
6624
// Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of
6644
6625
// a new class member i.e. it is the total size of all VarArgs.
6645
6626
IRB.CreateStore (TotalVAArgSize, MS.VAArgOverflowSizeTLS );
@@ -6649,7 +6630,7 @@ struct VarArgPowerPC32Helper : public VarArgHelperBase {
6649
6630
assert (!VAArgSize && !VAArgTLSCopy &&
6650
6631
" finalizeInstrumentation called twice" );
6651
6632
IRBuilder<> IRB (MSV.FnPrologueEnd );
6652
- VAArgSize = IRB.CreateLoad (MS. IntptrTy , MS.VAArgOverflowSizeTLS );
6633
+ VAArgSize = IRB.CreateLoad (IRB. getInt32Ty () , MS.VAArgOverflowSizeTLS );
6653
6634
Value *CopySize = VAArgSize;
6654
6635
6655
6636
if (!VAStartInstrumentationList.empty ()) {
@@ -6663,7 +6644,7 @@ struct VarArgPowerPC32Helper : public VarArgHelperBase {
6663
6644
6664
6645
Value *SrcSize = IRB.CreateBinaryIntrinsic (
6665
6646
Intrinsic::umin, CopySize,
6666
- ConstantInt::get (MS. IntptrTy , kParamTLSSize ));
6647
+ ConstantInt::get (IRB. getInt32Ty () , kParamTLSSize ));
6667
6648
IRB.CreateMemCpy (VAArgTLSCopy, kShadowTLSAlignment , MS.VAArgTLS ,
6668
6649
kShadowTLSAlignment , SrcSize);
6669
6650
}
@@ -6674,25 +6655,71 @@ struct VarArgPowerPC32Helper : public VarArgHelperBase {
6674
6655
for (CallInst *OrigInst : VAStartInstrumentationList) {
6675
6656
NextNodeIRBuilder IRB (OrigInst);
6676
6657
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;
6678
6661
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 ));
6685
6665
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 );
6686
6671
Value *RegSaveAreaPtr = IRB.CreateLoad (MS.PtrTy , RegSaveAreaPtrPtr);
6687
- Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
6672
+
6688
6673
const DataLayout &DL = F.getDataLayout ();
6689
- unsigned IntptrSize = DL.getTypeStoreSize (MS. IntptrTy );
6674
+ unsigned IntptrSize = DL.getTypeStoreSize (IRB. getInt32Ty () );
6690
6675
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
+ }
6696
6723
}
6697
6724
}
6698
6725
};
@@ -7220,10 +7247,10 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,
7220
7247
// On PowerPC32 VAListTag is a struct
7221
7248
// {char, char, i16 padding, char *, char *}
7222
7249
if (TargetTriple.isPPC32 ())
7223
- return new VarArgPowerPC32Helper (Func, Msan, Visitor, /* VAListTagSize= */ 12 );
7250
+ return new VarArgPowerPC32Helper (Func, Msan, Visitor);
7224
7251
7225
7252
if (TargetTriple.isPPC64 ())
7226
- return new VarArgPowerPC64Helper (Func, Msan, Visitor, /* VAListTagSize= */ 8 );
7253
+ return new VarArgPowerPC64Helper (Func, Msan, Visitor);
7227
7254
7228
7255
if (TargetTriple.isRISCV32 ())
7229
7256
return new VarArgRISCVHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 4 );
0 commit comments