diff options
Diffstat (limited to 'lib/IR')
-rw-r--r-- | lib/IR/Globals.cpp | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/lib/IR/Globals.cpp b/lib/IR/Globals.cpp index 0ec54fe3c0..d64046a7bf 100644 --- a/lib/IR/Globals.cpp +++ b/lib/IR/Globals.cpp @@ -15,6 +15,7 @@ #include "llvm/IR/GlobalValue.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalVariable.h" @@ -282,3 +283,27 @@ GlobalObject *GlobalAlias::getAliasedGlobal() { return cast<GlobalObject>(GV); } } + +uint64_t GlobalAlias::calculateOffset(const DataLayout &DL) const { + uint64_t Offset = 0; + const Constant *C = this; + while (C) { + if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(C)) { + C = GA->getAliasee(); + } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) { + if (CE->getOpcode() == Instruction::GetElementPtr) { + std::vector<Value*> Args; + for (unsigned I = 1; I < CE->getNumOperands(); ++I) + Args.push_back(CE->getOperand(I)); + Offset += DL.getIndexedOffset(CE->getOperand(0)->getType(), Args); + } + C = CE->getOperand(0); + } else if (isa<GlobalValue>(C)) { + return Offset; + } else { + assert(0 && "Unexpected type in alias chain!"); + return 0; + } + } + return Offset; +} |