Skip to content

Commit 1fc6217

Browse files
author
Kamil Kashapov
committed
Split PPC VarArg Helper into PPC32 and PPC64
1 parent 0a21ef9 commit 1fc6217

File tree

1 file changed

+159
-6
lines changed

1 file changed

+159
-6
lines changed

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 159 additions & 6 deletions
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;
@@ -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

Comments
 (0)