diff options
Diffstat (limited to 'llvm/lib/IR')
-rw-r--r-- | llvm/lib/IR/AsmWriter.cpp | 45 | ||||
-rw-r--r-- | llvm/lib/IR/Instruction.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/IR/Instructions.cpp | 83 | ||||
-rw-r--r-- | llvm/lib/IR/Value.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 21 |
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)), |