summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/IR')
-rw-r--r--llvm/lib/IR/AsmWriter.cpp45
-rw-r--r--llvm/lib/IR/Instruction.cpp11
-rw-r--r--llvm/lib/IR/Instructions.cpp83
-rw-r--r--llvm/lib/IR/Value.cpp3
-rw-r--r--llvm/lib/IR/Verifier.cpp21
5 files changed, 160 insertions, 3 deletions
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 980de9ab1ee..af3db5186a2 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -3836,6 +3836,51 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
writeOperand(II->getNormalDest(), true);
Out << " unwind ";
writeOperand(II->getUnwindDest(), true);
+ } else if (const CallBrInst *CBI = dyn_cast<CallBrInst>(&I)) {
+ Operand = CBI->getCalledValue();
+ FunctionType *FTy = CBI->getFunctionType();
+ Type *RetTy = FTy->getReturnType();
+ const AttributeList &PAL = CBI->getAttributes();
+
+ // Print the calling convention being used.
+ if (CBI->getCallingConv() != CallingConv::C) {
+ Out << " ";
+ PrintCallingConv(CBI->getCallingConv(), Out);
+ }
+
+ if (PAL.hasAttributes(AttributeList::ReturnIndex))
+ Out << ' ' << PAL.getAsString(AttributeList::ReturnIndex);
+
+ // If possible, print out the short form of the callbr instruction. We can
+ // only do this if the first argument is a pointer to a nonvararg function,
+ // and if the return type is not a pointer to a function.
+ //
+ Out << ' ';
+ TypePrinter.print(FTy->isVarArg() ? FTy : RetTy, Out);
+ Out << ' ';
+ writeOperand(Operand, false);
+ Out << '(';
+ for (unsigned op = 0, Eop = CBI->getNumArgOperands(); op < Eop; ++op) {
+ if (op)
+ Out << ", ";
+ writeParamOperand(CBI->getArgOperand(op), PAL.getParamAttributes(op));
+ }
+
+ Out << ')';
+ if (PAL.hasAttributes(AttributeList::FunctionIndex))
+ Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes());
+
+ writeOperandBundles(CBI);
+
+ Out << "\n to ";
+ writeOperand(CBI->getDefaultDest(), true);
+ Out << " [";
+ for (unsigned i = 0, e = CBI->getNumIndirectDests(); i != e; ++i) {
+ if (i != 0)
+ Out << ", ";
+ writeOperand(CBI->getIndirectDest(i), true);
+ }
+ Out << ']';
} else if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
Out << ' ';
if (AI->isUsedWithInAlloca())
diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index e031886bf15..32f3bfa66b1 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -301,6 +301,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case CatchRet: return "catchret";
case CatchPad: return "catchpad";
case CatchSwitch: return "catchswitch";
+ case CallBr: return "callbr";
// Standard unary operators...
case FNeg: return "fneg";
@@ -405,6 +406,10 @@ static bool haveSameSpecialState(const Instruction *I1, const Instruction *I2,
return CI->getCallingConv() == cast<InvokeInst>(I2)->getCallingConv() &&
CI->getAttributes() == cast<InvokeInst>(I2)->getAttributes() &&
CI->hasIdenticalOperandBundleSchema(*cast<InvokeInst>(I2));
+ if (const CallBrInst *CI = dyn_cast<CallBrInst>(I1))
+ return CI->getCallingConv() == cast<CallBrInst>(I2)->getCallingConv() &&
+ CI->getAttributes() == cast<CallBrInst>(I2)->getAttributes() &&
+ CI->hasIdenticalOperandBundleSchema(*cast<CallBrInst>(I2));
if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(I1))
return IVI->getIndices() == cast<InsertValueInst>(I2)->getIndices();
if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(I1))
@@ -516,6 +521,7 @@ bool Instruction::mayReadFromMemory() const {
return true;
case Instruction::Call:
case Instruction::Invoke:
+ case Instruction::CallBr:
return !cast<CallBase>(this)->doesNotAccessMemory();
case Instruction::Store:
return !cast<StoreInst>(this)->isUnordered();
@@ -535,6 +541,7 @@ bool Instruction::mayWriteToMemory() const {
return true;
case Instruction::Call:
case Instruction::Invoke:
+ case Instruction::CallBr:
return !cast<CallBase>(this)->onlyReadsMemory();
case Instruction::Load:
return !cast<LoadInst>(this)->isUnordered();
@@ -772,8 +779,8 @@ void Instruction::updateProfWeight(uint64_t S, uint64_t T) {
}
void Instruction::setProfWeight(uint64_t W) {
- assert((isa<CallInst>(this) || isa<InvokeInst>(this)) &&
- "Can only set weights for call and invoke instrucitons");
+ assert(isa<CallBase>(this) &&
+ "Can only set weights for call like instructions");
SmallVector<uint32_t, 1> Weights;
Weights.push_back(W);
MDBuilder MDB(getContext());
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index b9e6cd653ea..766c41188ff 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -256,6 +256,11 @@ void LandingPadInst::addClause(Constant *Val) {
Function *CallBase::getCaller() { return getParent()->getParent(); }
+unsigned CallBase::getNumSubclassExtraOperandsDynamic() const {
+ assert(getOpcode() == Instruction::CallBr && "Unexpected opcode!");
+ return cast<CallBrInst>(this)->getNumIndirectDests() + 1;
+}
+
bool CallBase::isIndirectCall() const {
const Value *V = getCalledValue();
if (isa<Function>(V) || isa<Constant>(V))
@@ -727,6 +732,76 @@ LandingPadInst *InvokeInst::getLandingPadInst() const {
}
//===----------------------------------------------------------------------===//
+// CallBrInst Implementation
+//===----------------------------------------------------------------------===//
+
+void CallBrInst::init(FunctionType *FTy, Value *Fn, BasicBlock *Fallthrough,
+ ArrayRef<BasicBlock *> IndirectDests,
+ ArrayRef<Value *> Args,
+ ArrayRef<OperandBundleDef> Bundles,
+ const Twine &NameStr) {
+ this->FTy = FTy;
+
+ assert((int)getNumOperands() ==
+ ComputeNumOperands(Args.size(), IndirectDests.size(),
+ CountBundleInputs(Bundles)) &&
+ "NumOperands not set up?");
+ NumIndirectDests = IndirectDests.size();
+ setDefaultDest(Fallthrough);
+ for (unsigned i = 0; i != NumIndirectDests; ++i)
+ setIndirectDest(i, IndirectDests[i]);
+ setCalledOperand(Fn);
+
+#ifndef NDEBUG
+ assert(((Args.size() == FTy->getNumParams()) ||
+ (FTy->isVarArg() && Args.size() > FTy->getNumParams())) &&
+ "Calling a function with bad signature");
+
+ for (unsigned i = 0, e = Args.size(); i != e; i++)
+ assert((i >= FTy->getNumParams() ||
+ FTy->getParamType(i) == Args[i]->getType()) &&
+ "Calling a function with a bad signature!");
+#endif
+
+ std::copy(Args.begin(), Args.end(), op_begin());
+
+ auto It = populateBundleOperandInfos(Bundles, Args.size());
+ (void)It;
+ assert(It + 2 + IndirectDests.size() == op_end() && "Should add up!");
+
+ setName(NameStr);
+}
+
+CallBrInst::CallBrInst(const CallBrInst &CBI)
+ : CallBase(CBI.Attrs, CBI.FTy, CBI.getType(), Instruction::CallBr,
+ OperandTraits<CallBase>::op_end(this) - CBI.getNumOperands(),
+ CBI.getNumOperands()) {
+ setCallingConv(CBI.getCallingConv());
+ std::copy(CBI.op_begin(), CBI.op_end(), op_begin());
+ std::copy(CBI.bundle_op_info_begin(), CBI.bundle_op_info_end(),
+ bundle_op_info_begin());
+ SubclassOptionalData = CBI.SubclassOptionalData;
+ NumIndirectDests = CBI.NumIndirectDests;
+}
+
+CallBrInst *CallBrInst::Create(CallBrInst *CBI, ArrayRef<OperandBundleDef> OpB,
+ Instruction *InsertPt) {
+ std::vector<Value *> Args(CBI->arg_begin(), CBI->arg_end());
+
+ auto *NewCBI = CallBrInst::Create(CBI->getFunctionType(),
+ CBI->getCalledValue(),
+ CBI->getDefaultDest(),
+ CBI->getIndirectDests(),
+ Args, OpB, CBI->getName(), InsertPt);
+ NewCBI->setCallingConv(CBI->getCallingConv());
+ NewCBI->SubclassOptionalData = CBI->SubclassOptionalData;
+ NewCBI->setAttributes(CBI->getAttributes());
+ NewCBI->setDebugLoc(CBI->getDebugLoc());
+ NewCBI->NumIndirectDests = CBI->NumIndirectDests;
+ return NewCBI;
+}
+
+//===----------------------------------------------------------------------===//
// ReturnInst Implementation
//===----------------------------------------------------------------------===//
@@ -3996,6 +4071,14 @@ InvokeInst *InvokeInst::cloneImpl() const {
return new(getNumOperands()) InvokeInst(*this);
}
+CallBrInst *CallBrInst::cloneImpl() const {
+ if (hasOperandBundles()) {
+ unsigned DescriptorBytes = getNumOperandBundles() * sizeof(BundleOpInfo);
+ return new (getNumOperands(), DescriptorBytes) CallBrInst(*this);
+ }
+ return new (getNumOperands()) CallBrInst(*this);
+}
+
ResumeInst *ResumeInst::cloneImpl() const { return new (1) ResumeInst(*this); }
CleanupReturnInst *CleanupReturnInst::cloneImpl() const {
diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp
index 2951cf1ed64..38eed76fe45 100644
--- a/llvm/lib/IR/Value.cpp
+++ b/llvm/lib/IR/Value.cpp
@@ -57,7 +57,8 @@ Value::Value(Type *ty, unsigned scid)
// FIXME: Why isn't this in the subclass gunk??
// Note, we cannot call isa<CallInst> before the CallInst has been
// constructed.
- if (SubclassID == Instruction::Call || SubclassID == Instruction::Invoke)
+ if (SubclassID == Instruction::Call || SubclassID == Instruction::Invoke ||
+ SubclassID == Instruction::CallBr)
assert((VTy->isFirstClassType() || VTy->isVoidTy() || VTy->isStructTy()) &&
"invalid CallInst type!");
else if (SubclassID != BasicBlockVal &&
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 404749b2d8e..4a39ff40fd1 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -466,6 +466,7 @@ private:
void visitReturnInst(ReturnInst &RI);
void visitSwitchInst(SwitchInst &SI);
void visitIndirectBrInst(IndirectBrInst &BI);
+ void visitCallBrInst(CallBrInst &CBI);
void visitSelectInst(SelectInst &SI);
void visitUserOp1(Instruction &I);
void visitUserOp2(Instruction &I) { visitUserOp1(I); }
@@ -2450,6 +2451,26 @@ void Verifier::visitIndirectBrInst(IndirectBrInst &BI) {
visitTerminator(BI);
}
+void Verifier::visitCallBrInst(CallBrInst &CBI) {
+ Assert(CBI.isInlineAsm(), "Callbr is currently only used for asm-goto!",
+ &CBI);
+ Assert(CBI.getType()->isVoidTy(), "Callbr return value is not supported!",
+ &CBI);
+ for (unsigned i = 0, e = CBI.getNumSuccessors(); i != e; ++i)
+ Assert(CBI.getSuccessor(i)->getType()->isLabelTy(),
+ "Callbr successors must all have pointer type!", &CBI);
+ for (unsigned i = 0, e = CBI.getNumOperands(); i != e; ++i) {
+ Assert(i >= CBI.getNumArgOperands() || !isa<BasicBlock>(CBI.getOperand(i)),
+ "Using an unescaped label as a callbr argument!", &CBI);
+ if (isa<BasicBlock>(CBI.getOperand(i)))
+ for (unsigned j = i + 1; j != e; ++j)
+ Assert(CBI.getOperand(i) != CBI.getOperand(j),
+ "Duplicate callbr destination!", &CBI);
+ }
+
+ visitTerminator(CBI);
+}
+
void Verifier::visitSelectInst(SelectInst &SI) {
Assert(!SelectInst::areInvalidOperands(SI.getOperand(0), SI.getOperand(1),
SI.getOperand(2)),
OpenPOWER on IntegriCloud