summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/IR/BasicBlock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/IR/BasicBlock.cpp')
-rw-r--r--contrib/llvm/lib/IR/BasicBlock.cpp60
1 files changed, 44 insertions, 16 deletions
diff --git a/contrib/llvm/lib/IR/BasicBlock.cpp b/contrib/llvm/lib/IR/BasicBlock.cpp
index ba07433..98a3062 100644
--- a/contrib/llvm/lib/IR/BasicBlock.cpp
+++ b/contrib/llvm/lib/IR/BasicBlock.cpp
@@ -19,7 +19,6 @@
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/LeakDetector.h"
#include "llvm/IR/Type.h"
#include <algorithm>
using namespace llvm;
@@ -47,20 +46,24 @@ BasicBlock::BasicBlock(LLVMContext &C, const Twine &Name, Function *NewParent,
BasicBlock *InsertBefore)
: Value(Type::getLabelTy(C), Value::BasicBlockVal), Parent(nullptr) {
- // Make sure that we get added to a function
- LeakDetector::addGarbageObject(this);
-
- if (InsertBefore) {
- assert(NewParent &&
+ if (NewParent)
+ insertInto(NewParent, InsertBefore);
+ else
+ assert(!InsertBefore &&
"Cannot insert block before another block with no function!");
- NewParent->getBasicBlockList().insert(InsertBefore, this);
- } else if (NewParent) {
- NewParent->getBasicBlockList().push_back(this);
- }
setName(Name);
}
+void BasicBlock::insertInto(Function *NewParent, BasicBlock *InsertBefore) {
+ assert(NewParent && "Expected a parent");
+ assert(!Parent && "Already has a parent");
+
+ if (InsertBefore)
+ NewParent->getBasicBlockList().insert(InsertBefore, this);
+ else
+ NewParent->getBasicBlockList().push_back(this);
+}
BasicBlock::~BasicBlock() {
// If the address of the block is taken and it is being deleted (e.g. because
@@ -87,14 +90,8 @@ BasicBlock::~BasicBlock() {
}
void BasicBlock::setParent(Function *parent) {
- if (getParent())
- LeakDetector::addGarbageObject(this);
-
// Set Parent=parent, updating instruction symtab entries as appropriate.
InstList.setSymTabObject(&Parent, parent);
-
- if (getParent())
- LeakDetector::removeGarbageObject(this);
}
void BasicBlock::removeFromParent() {
@@ -131,6 +128,37 @@ const TerminatorInst *BasicBlock::getTerminator() const {
return dyn_cast<TerminatorInst>(&InstList.back());
}
+CallInst *BasicBlock::getTerminatingMustTailCall() {
+ if (InstList.empty())
+ return nullptr;
+ ReturnInst *RI = dyn_cast<ReturnInst>(&InstList.back());
+ if (!RI || RI == &InstList.front())
+ return nullptr;
+
+ Instruction *Prev = RI->getPrevNode();
+ if (!Prev)
+ return nullptr;
+
+ if (Value *RV = RI->getReturnValue()) {
+ if (RV != Prev)
+ return nullptr;
+
+ // Look through the optional bitcast.
+ if (auto *BI = dyn_cast<BitCastInst>(Prev)) {
+ RV = BI->getOperand(0);
+ Prev = BI->getPrevNode();
+ if (!Prev || RV != Prev)
+ return nullptr;
+ }
+ }
+
+ if (auto *CI = dyn_cast<CallInst>(Prev)) {
+ if (CI->isMustTailCall())
+ return CI;
+ }
+ return nullptr;
+}
+
Instruction* BasicBlock::getFirstNonPHI() {
BasicBlock::iterator i = begin();
// All valid basic blocks should have a terminator,
OpenPOWER on IntegriCloud