[Attributor] Don't access pointer elem type in constructPointer (NFC)

Splitting this out as the change is non-trivial: The way this code
handled pointer types doesn't really make sense, as GEPs can only
apply an offset to the outermost pointer, but can't drill down
into interior pointer types (which would require dereferencing
memory).

Instead give special treatment to the first (pointer) index.
I've hardcoded it to zero as that's the only way the function is
used right now, but handling non-zero indexes would be
straightforward.

The original goal here was to have an element type for CreateGEP.
This commit is contained in:
Nikita Popov 2021-03-11 21:31:46 +01:00
parent 87fd09b25f
commit 2fe85dd289
1 changed files with 44 additions and 46 deletions

View File

@ -190,58 +190,55 @@ static const Value *getPointerOperand(const Instruction *I,
///
/// TODO: This could probably live somewhere more prominantly if it doesn't
/// already exist.
static Value *constructPointer(Type *ResTy, Value *Ptr, int64_t Offset,
IRBuilder<NoFolder> &IRB, const DataLayout &DL) {
static Value *constructPointer(Type *ResTy, Type *PtrElemTy, Value *Ptr,
int64_t Offset, IRBuilder<NoFolder> &IRB,
const DataLayout &DL) {
assert(Offset >= 0 && "Negative offset not supported yet!");
LLVM_DEBUG(dbgs() << "Construct pointer: " << *Ptr << " + " << Offset
<< "-bytes as " << *ResTy << "\n");
// The initial type we are trying to traverse to get nice GEPs.
Type *Ty = Ptr->getType();
if (Offset) {
SmallVector<Value *, 4> Indices;
std::string GEPName = Ptr->getName().str() + ".0";
SmallVector<Value *, 4> Indices;
std::string GEPName = Ptr->getName().str();
while (Offset) {
uint64_t Idx, Rem;
// Add 0 index to look through the pointer.
assert((uint64_t)Offset < DL.getTypeAllocSize(PtrElemTy) &&
"Offset out of bounds");
Indices.push_back(Constant::getNullValue(IRB.getInt32Ty()));
Type *Ty = PtrElemTy;
do {
auto *STy = dyn_cast<StructType>(Ty);
if (!STy)
// Non-aggregate type, we cast and make byte-wise progress now.
break;
if (auto *STy = dyn_cast<StructType>(Ty)) {
const StructLayout *SL = DL.getStructLayout(STy);
if (int64_t(SL->getSizeInBytes()) < Offset)
break;
Idx = SL->getElementContainingOffset(Offset);
uint64_t Idx = SL->getElementContainingOffset(Offset);
assert(Idx < STy->getNumElements() && "Offset calculation error!");
Rem = Offset - SL->getElementOffset(Idx);
uint64_t Rem = Offset - SL->getElementOffset(Idx);
Ty = STy->getElementType(Idx);
} else if (auto *PTy = dyn_cast<PointerType>(Ty)) {
Ty = PTy->getElementType();
if (!Ty->isSized())
break;
uint64_t ElementSize = DL.getTypeAllocSize(Ty);
assert(ElementSize && "Expected type with size!");
Idx = Offset / ElementSize;
Rem = Offset % ElementSize;
} else {
// Non-aggregate type, we cast and make byte-wise progress now.
break;
LLVM_DEBUG(errs() << "Ty: " << *Ty << " Offset: " << Offset
<< " Idx: " << Idx << " Rem: " << Rem << "\n");
GEPName += "." + std::to_string(Idx);
Indices.push_back(ConstantInt::get(IRB.getInt32Ty(), Idx));
Offset = Rem;
} while (Offset);
// Create a GEP for the indices collected above.
Ptr = IRB.CreateGEP(PtrElemTy, Ptr, Indices, GEPName);
// If an offset is left we use byte-wise adjustment.
if (Offset) {
Ptr = IRB.CreateBitCast(Ptr, IRB.getInt8PtrTy());
Ptr = IRB.CreateGEP(IRB.getInt8Ty(), Ptr, IRB.getInt32(Offset),
GEPName + ".b" + Twine(Offset));
}
LLVM_DEBUG(errs() << "Ty: " << *Ty << " Offset: " << Offset
<< " Idx: " << Idx << " Rem: " << Rem << "\n");
GEPName += "." + std::to_string(Idx);
Indices.push_back(ConstantInt::get(IRB.getInt32Ty(), Idx));
Offset = Rem;
}
// Create a GEP if we collected indices above.
if (Indices.size())
Ptr = IRB.CreateGEP(Ptr, Indices, GEPName);
// If an offset is left we use byte-wise adjustment.
if (Offset) {
Ptr = IRB.CreateBitCast(Ptr, IRB.getInt8PtrTy());
Ptr = IRB.CreateGEP(Ptr, IRB.getInt32(Offset),
GEPName + ".b" + Twine(Offset));
}
// Ensure the result has the requested type.
@ -5607,7 +5604,8 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
Type *PointeeTy = PrivStructType->getElementType(u)->getPointerTo();
Value *Ptr = constructPointer(
PointeeTy, &Base, PrivStructLayout->getElementOffset(u), IRB, DL);
PointeeTy, PrivType, &Base, PrivStructLayout->getElementOffset(u),
IRB, DL);
new StoreInst(F.getArg(ArgNo + u), Ptr, &IP);
}
} else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
@ -5615,8 +5613,8 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
Type *PointeePtrTy = PointeeTy->getPointerTo();
uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
Value *Ptr =
constructPointer(PointeePtrTy, &Base, u * PointeeTySize, IRB, DL);
Value *Ptr = constructPointer(
PointeePtrTy, PrivType, &Base, u * PointeeTySize, IRB, DL);
new StoreInst(F.getArg(ArgNo + u), Ptr, &IP);
}
} else {
@ -5646,7 +5644,7 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
Type *PointeeTy = PrivStructType->getElementType(u);
Value *Ptr =
constructPointer(PointeeTy->getPointerTo(), Base,
constructPointer(PointeeTy->getPointerTo(), PrivType, Base,
PrivStructLayout->getElementOffset(u), IRB, DL);
LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP);
L->setAlignment(Alignment);
@ -5657,8 +5655,8 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
Type *PointeePtrTy = PointeeTy->getPointerTo();
for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
Value *Ptr =
constructPointer(PointeePtrTy, Base, u * PointeeTySize, IRB, DL);
Value *Ptr = constructPointer(
PointeePtrTy, PrivType, Base, u * PointeeTySize, IRB, DL);
LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP);
L->setAlignment(Alignment);
ReplacementValues.push_back(L);