aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/ValueMapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Utils/ValueMapper.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/ValueMapper.cpp73
1 files changed, 64 insertions, 9 deletions
diff --git a/llvm/lib/Transforms/Utils/ValueMapper.cpp b/llvm/lib/Transforms/Utils/ValueMapper.cpp
index 01a29cd..6362693 100644
--- a/llvm/lib/Transforms/Utils/ValueMapper.cpp
+++ b/llvm/lib/Transforms/Utils/ValueMapper.cpp
@@ -30,12 +30,32 @@ void ValueMaterializer::materializeInitFor(GlobalValue *New, GlobalValue *Old) {
namespace {
+/// A GlobalValue whose initializer needs to be materialized.
+struct DelayedGlobalValueInit {
+ GlobalValue *Old;
+ GlobalValue *New;
+ DelayedGlobalValueInit(const GlobalValue *Old, GlobalValue *New)
+ : Old(const_cast<GlobalValue *>(Old)), New(New) {}
+};
+
+/// A basic block used in a BlockAddress whose function body is not yet
+/// materialized.
+struct DelayedBasicBlock {
+ BasicBlock *OldBB;
+ std::unique_ptr<BasicBlock> TempBB;
+ DelayedBasicBlock(const BlockAddress &Old)
+ : OldBB(Old.getBasicBlock()),
+ TempBB(BasicBlock::Create(Old.getContext())) {}
+};
+
class Mapper {
ValueToValueMapTy &VM;
RemapFlags Flags;
ValueMapTypeRemapper *TypeMapper;
ValueMaterializer *Materializer;
+ SmallVector<DelayedGlobalValueInit, 8> DelayedInits;
+ SmallVector<DelayedBasicBlock, 1> DelayedBBs;
SmallVector<MDNode *, 8> DistinctWorklist;
public:
@@ -55,6 +75,8 @@ public:
Metadata *mapMetadata(const Metadata *MD);
private:
+ Value *mapBlockAddress(const BlockAddress &BA);
+
/// Map metadata helper.
///
/// Co-recursively finds the mapping for MD. If this returns an MDNode, it's
@@ -110,8 +132,8 @@ Value *Mapper::mapValue(const Value *V) {
Materializer->materializeDeclFor(const_cast<Value *>(V))) {
VM[V] = NewV;
if (auto *NewGV = dyn_cast<GlobalValue>(NewV))
- Materializer->materializeInitFor(
- NewGV, const_cast<GlobalValue *>(cast<GlobalValue>(V)));
+ DelayedInits.push_back(
+ DelayedGlobalValueInit(cast<GlobalValue>(V), NewGV));
return NewV;
}
}
@@ -167,13 +189,10 @@ Value *Mapper::mapValue(const Value *V) {
Constant *C = const_cast<Constant*>(dyn_cast<Constant>(V));
if (!C)
return nullptr;
-
- if (BlockAddress *BA = dyn_cast<BlockAddress>(C)) {
- Function *F = cast<Function>(mapValue(BA->getFunction()));
- BasicBlock *BB = cast_or_null<BasicBlock>(mapValue(BA->getBasicBlock()));
- return VM[V] = BlockAddress::get(F, BB ? BB : BA->getBasicBlock());
- }
-
+
+ if (BlockAddress *BA = dyn_cast<BlockAddress>(C))
+ return mapBlockAddress(*BA);
+
// Otherwise, we have some other constant to remap. Start by checking to see
// if all operands have an identity remapping.
unsigned OpNo = 0, NumOperands = C->getNumOperands();
@@ -231,6 +250,23 @@ Value *Mapper::mapValue(const Value *V) {
return VM[V] = ConstantPointerNull::get(cast<PointerType>(NewTy));
}
+Value *Mapper::mapBlockAddress(const BlockAddress &BA) {
+ Function *F = cast<Function>(mapValue(BA.getFunction()));
+
+ // F may not have materialized its initializer. In that case, create a
+ // dummy basic block for now, and replace it once we've materialized all
+ // the initializers.
+ BasicBlock *BB;
+ if (F->isDeclaration()) {
+ BB = cast_or_null<BasicBlock>(mapValue(BA.getBasicBlock()));
+ } else {
+ DelayedBBs.push_back(DelayedBasicBlock(BA));
+ BB = DelayedBBs.back().TempBB.get();
+ }
+
+ return VM[&BA] = BlockAddress::get(F, BB ? BB : BA.getBasicBlock());
+}
+
Metadata *Mapper::mapToMetadata(const Metadata *Key, Metadata *Val) {
VM.MD()[Key].reset(Val);
return Val;
@@ -395,8 +431,27 @@ Metadata *Mapper::mapMetadata(const Metadata *MD) {
}
Mapper::~Mapper() {
+ // Remap the operands of distinct MDNodes.
while (!DistinctWorklist.empty())
remapOperands(*DistinctWorklist.pop_back_val());
+
+ // Materialize global initializers.
+ while (!DelayedInits.empty()) {
+ auto Init = DelayedInits.pop_back_val();
+ Materializer->materializeInitFor(Init.New, Init.Old);
+ }
+
+ // Process block addresses delayed until global inits.
+ while (!DelayedBBs.empty()) {
+ DelayedBasicBlock DBB = DelayedBBs.pop_back_val();
+ BasicBlock *BB = cast_or_null<BasicBlock>(mapValue(DBB.OldBB));
+ DBB.TempBB->replaceAllUsesWith(BB ? BB : DBB.OldBB);
+ }
+
+ // We don't expect any of these to grow after clearing.
+ assert(DistinctWorklist.empty());
+ assert(DelayedInits.empty());
+ assert(DelayedBBs.empty());
}
MDNode *llvm::MapMetadata(const MDNode *MD, ValueToValueMapTy &VM,