Skip to content

Commit b712068

Browse files
authored
[nfc][Msan] Split PPC VarArg Helper into PPC32 and PPC64 (llvm#134860)
As discussed in llvm#131827, copied ppc32 helper from ppc64. No functional changes have been made.
1 parent 1d0f835 commit b712068

File tree

1 file changed

+160
-7
lines changed

1 file changed

+160
-7
lines changed

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

+160-7
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)