summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2016-12-09 00:33:27 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2016-12-09 00:33:27 +0000
commit7a1e5bbe4e63c41dffa6d19668ebe72cda3f9803 (patch)
tree2ce564b2df30fa39610929bf6e5bdedbfc0bf649 /llvm/lib
parent313b326bb6a5bc240f2cfeb9f403fe9f5d18bc4e (diff)
downloadbcm5719-llvm-7a1e5bbe4e63c41dffa6d19668ebe72cda3f9803.tar.gz
bcm5719-llvm-7a1e5bbe4e63c41dffa6d19668ebe72cda3f9803.zip
Make WholeProgramDevirt understand ConstStruct vtables.
Based on a patch by LemonBoy! Differential Revision: https://reviews.llvm.org/D26581 llvm-svn: 289162
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp50
1 files changed, 37 insertions, 13 deletions
diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
index 7ef5f247392..9c80a2ae690 100644
--- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
+++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
@@ -293,6 +293,7 @@ struct DevirtModule {
void buildTypeIdentifierMap(
std::vector<VTableBits> &Bits,
DenseMap<Metadata *, std::set<TypeMemberInfo>> &TypeIdMap);
+ Constant *getValueAtOffset(Constant *I, uint64_t Offset);
bool
tryFindVirtualCallTargets(std::vector<VirtualCallTarget> &TargetsForSlot,
const std::set<TypeMemberInfo> &TypeMemberInfos,
@@ -382,6 +383,38 @@ void DevirtModule::buildTypeIdentifierMap(
}
}
+Constant *DevirtModule::getValueAtOffset(Constant *I, uint64_t Offset) {
+ const DataLayout &DL = M.getDataLayout();
+ unsigned Op;
+
+ if (auto *C = dyn_cast<ConstantStruct>(I)) {
+ const StructLayout *SL = DL.getStructLayout(C->getType());
+
+ if (Offset >= SL->getSizeInBytes())
+ return nullptr;
+
+ Op = SL->getElementContainingOffset(Offset);
+
+ if (Offset != SL->getElementOffset(Op))
+ return nullptr;
+
+ } else if (auto *C = dyn_cast<ConstantArray>(I)) {
+ ArrayType *VTableTy = C->getType();
+ uint64_t ElemSize = DL.getTypeAllocSize(VTableTy->getElementType());
+
+ if (Offset % ElemSize != 0)
+ return nullptr;
+
+ Op = Offset / ElemSize;
+
+ if (Op >= C->getNumOperands())
+ return nullptr;
+ } else
+ return nullptr;
+
+ return cast<Constant>(I->getOperand(Op));
+}
+
bool DevirtModule::tryFindVirtualCallTargets(
std::vector<VirtualCallTarget> &TargetsForSlot,
const std::set<TypeMemberInfo> &TypeMemberInfos, uint64_t ByteOffset) {
@@ -389,22 +422,13 @@ bool DevirtModule::tryFindVirtualCallTargets(
if (!TM.Bits->GV->isConstant())
return false;
- auto Init = dyn_cast<ConstantArray>(TM.Bits->GV->getInitializer());
- if (!Init)
- return false;
- ArrayType *VTableTy = Init->getType();
-
- uint64_t ElemSize =
- M.getDataLayout().getTypeAllocSize(VTableTy->getElementType());
- uint64_t GlobalSlotOffset = TM.Offset + ByteOffset;
- if (GlobalSlotOffset % ElemSize != 0)
- return false;
+ Constant *I = TM.Bits->GV->getInitializer();
+ Value *V = getValueAtOffset(I, TM.Offset + ByteOffset);
- unsigned Op = GlobalSlotOffset / ElemSize;
- if (Op >= Init->getNumOperands())
+ if (!V)
return false;
- auto Fn = dyn_cast<Function>(Init->getOperand(Op)->stripPointerCasts());
+ auto Fn = dyn_cast<Function>(V->stripPointerCasts());
if (!Fn)
return false;
OpenPOWER on IntegriCloud