aboutsummaryrefslogtreecommitdiffstats
path: root/lib/VMCore
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-10-27 19:13:16 +0000
committerChris Lattner <sabre@nondot.org>2009-10-27 19:13:16 +0000
commitf9be95f867745b6754b2402b9b72f9eaeabd637f (patch)
tree1f51be80a5e575555d713f49a374c10bf298e96c /lib/VMCore
parent76b39e88e470171292850d8cebc5d54227b43883 (diff)
downloadexternal_llvm-f9be95f867745b6754b2402b9b72f9eaeabd637f.zip
external_llvm-f9be95f867745b6754b2402b9b72f9eaeabd637f.tar.gz
external_llvm-f9be95f867745b6754b2402b9b72f9eaeabd637f.tar.bz2
add enough support for indirect branch for the feature test to pass
(assembler,asmprinter, bc reader+writer) and document it. Codegen currently aborts on it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85274 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore')
-rw-r--r--lib/VMCore/AsmWriter.cpp15
-rw-r--r--lib/VMCore/Instruction.cpp1
-rw-r--r--lib/VMCore/Instructions.cpp121
3 files changed, 136 insertions, 1 deletions
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index 59ee375..5a92432 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -1832,7 +1832,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
writeOperand(BI.getSuccessor(1), true);
} else if (isa<SwitchInst>(I)) {
- // Special case switch statement to get formatting nice and correct...
+ // Special case switch instruction to get formatting nice and correct.
Out << ' ';
writeOperand(Operand , true);
Out << ", ";
@@ -1846,6 +1846,19 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
writeOperand(I.getOperand(op+1), true);
}
Out << "\n ]";
+ } else if (isa<IndBrInst>(I)) {
+ // Special case indbr instruction to get formatting nice and correct.
+ Out << ' ';
+ writeOperand(Operand, true);
+ Out << ", ";
+ Out << " [";
+
+ for (unsigned i = 1, e = I.getNumOperands(); i != e; ++i) {
+ if (i != 1)
+ Out << ", ";
+ writeOperand(I.getOperand(i), true);
+ }
+ Out << ']';
} else if (isa<PHINode>(I)) {
Out << ' ';
TypePrinter.print(I.getType(), Out);
diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp
index def7b3b..4e89222 100644
--- a/lib/VMCore/Instruction.cpp
+++ b/lib/VMCore/Instruction.cpp
@@ -103,6 +103,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case Ret: return "ret";
case Br: return "br";
case Switch: return "switch";
+ case IndBr: return "indbr";
case Invoke: return "invoke";
case Unwind: return "unwind";
case Unreachable: return "unreachable";
diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp
index 02d5af0..61b8044 100644
--- a/lib/VMCore/Instructions.cpp
+++ b/lib/VMCore/Instructions.cpp
@@ -3086,6 +3086,118 @@ void SwitchInst::setSuccessorV(unsigned idx, BasicBlock *B) {
setSuccessor(idx, B);
}
+//===----------------------------------------------------------------------===//
+// SwitchInst Implementation
+//===----------------------------------------------------------------------===//
+
+void IndBrInst::init(Value *Address, unsigned NumDests) {
+ assert(Address);
+ ReservedSpace = 1+NumDests;
+ NumOperands = 1;
+ OperandList = allocHungoffUses(ReservedSpace);
+
+ OperandList[0] = Address;
+}
+
+
+/// resizeOperands - resize operands - This adjusts the length of the operands
+/// list according to the following behavior:
+/// 1. If NumOps == 0, grow the operand list in response to a push_back style
+/// of operation. This grows the number of ops by 2 times.
+/// 2. If NumOps > NumOperands, reserve space for NumOps operands.
+/// 3. If NumOps == NumOperands, trim the reserved space.
+///
+void IndBrInst::resizeOperands(unsigned NumOps) {
+ unsigned e = getNumOperands();
+ if (NumOps == 0) {
+ NumOps = e*2;
+ } else if (NumOps*2 > NumOperands) {
+ // No resize needed.
+ if (ReservedSpace >= NumOps) return;
+ } else if (NumOps == NumOperands) {
+ if (ReservedSpace == NumOps) return;
+ } else {
+ return;
+ }
+
+ ReservedSpace = NumOps;
+ Use *NewOps = allocHungoffUses(NumOps);
+ Use *OldOps = OperandList;
+ for (unsigned i = 0; i != e; ++i)
+ NewOps[i] = OldOps[i];
+ OperandList = NewOps;
+ if (OldOps) Use::zap(OldOps, OldOps + e, true);
+}
+
+IndBrInst::IndBrInst(Value *Address, unsigned NumCases,
+ Instruction *InsertBefore)
+: TerminatorInst(Type::getVoidTy(Address->getContext()), Instruction::IndBr,
+ 0, 0, InsertBefore) {
+ init(Address, NumCases);
+}
+
+IndBrInst::IndBrInst(Value *Address, unsigned NumCases, BasicBlock *InsertAtEnd)
+: TerminatorInst(Type::getVoidTy(Address->getContext()), Instruction::IndBr,
+ 0, 0, InsertAtEnd) {
+ init(Address, NumCases);
+}
+
+IndBrInst::IndBrInst(const IndBrInst &IBI)
+ : TerminatorInst(Type::getVoidTy(IBI.getContext()), Instruction::IndBr,
+ allocHungoffUses(IBI.getNumOperands()),
+ IBI.getNumOperands()) {
+ Use *OL = OperandList, *InOL = IBI.OperandList;
+ for (unsigned i = 0, E = IBI.getNumOperands(); i != E; ++i)
+ OL[i] = InOL[i];
+ SubclassOptionalData = IBI.SubclassOptionalData;
+}
+
+IndBrInst::~IndBrInst() {
+ dropHungoffUses(OperandList);
+}
+
+/// addDestination - Add a destination.
+///
+void IndBrInst::addDestination(BasicBlock *DestBB) {
+ unsigned OpNo = NumOperands;
+ if (OpNo+1 > ReservedSpace)
+ resizeOperands(0); // Get more space!
+ // Initialize some new operands.
+ assert(OpNo < ReservedSpace && "Growing didn't work!");
+ NumOperands = OpNo+1;
+ OperandList[OpNo] = DestBB;
+}
+
+/// removeDestination - This method removes the specified successor from the
+/// indbr instruction.
+void IndBrInst::removeDestination(unsigned idx) {
+ assert(idx < getNumOperands()-1 && "Successor index out of range!");
+
+ unsigned NumOps = getNumOperands();
+ Use *OL = OperandList;
+
+ // Replace this value with the last one.
+ OL[idx+1] = OL[NumOps-1];
+
+ // Nuke the last value.
+ OL[NumOps-1].set(0);
+ NumOperands = NumOps-1;
+}
+
+BasicBlock *IndBrInst::getSuccessorV(unsigned idx) const {
+ return getSuccessor(idx);
+}
+unsigned IndBrInst::getNumSuccessorsV() const {
+ return getNumSuccessors();
+}
+void IndBrInst::setSuccessorV(unsigned idx, BasicBlock *B) {
+ setSuccessor(idx, B);
+}
+
+//===----------------------------------------------------------------------===//
+// clone() implementations
+//===----------------------------------------------------------------------===//
+
// Define these methods here so vtables don't get emitted into every translation
// unit that uses these classes.
@@ -3410,6 +3522,15 @@ SwitchInst *SwitchInst::clone() const {
return New;
}
+IndBrInst *IndBrInst::clone() const {
+ IndBrInst *New = new IndBrInst(*this);
+ New->SubclassOptionalData = SubclassOptionalData;
+ if (hasMetadata())
+ getContext().pImpl->TheMetadata.ValueIsCloned(this, New);
+ return New;
+}
+
+
InvokeInst *InvokeInst::clone() const {
InvokeInst *New = new(getNumOperands()) InvokeInst(*this);
New->SubclassOptionalData = SubclassOptionalData;