aboutsummaryrefslogtreecommitdiffstats
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
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
-rw-r--r--docs/LangRef.html50
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h5
-rw-r--r--include/llvm/Instruction.def121
-rw-r--r--include/llvm/Instructions.h103
-rw-r--r--include/llvm/Support/InstVisitor.h1
-rw-r--r--lib/AsmParser/LLLexer.cpp1
-rw-r--r--lib/AsmParser/LLParser.cpp104
-rw-r--r--lib/AsmParser/LLParser.h9
-rw-r--r--lib/AsmParser/LLToken.h2
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp25
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp9
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp5
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuild.h2
-rw-r--r--lib/VMCore/AsmWriter.cpp15
-rw-r--r--lib/VMCore/Instruction.cpp1
-rw-r--r--lib/VMCore/Instructions.cpp121
-rw-r--r--test/Feature/terminators.ll11
17 files changed, 483 insertions, 102 deletions
diff --git a/docs/LangRef.html b/docs/LangRef.html
index 73ee31b..c12bacf 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -110,6 +110,7 @@
<li><a href="#i_ret">'<tt>ret</tt>' Instruction</a></li>
<li><a href="#i_br">'<tt>br</tt>' Instruction</a></li>
<li><a href="#i_switch">'<tt>switch</tt>' Instruction</a></li>
+ <li><a href="#i_indbr">'<tt>indbr</tt>' Instruction</a></li>
<li><a href="#i_invoke">'<tt>invoke</tt>' Instruction</a></li>
<li><a href="#i_unwind">'<tt>unwind</tt>' Instruction</a></li>
<li><a href="#i_unreachable">'<tt>unreachable</tt>' Instruction</a></li>
@@ -2511,6 +2512,7 @@ Instructions</a> </div>
'<a href="#i_ret"><tt>ret</tt></a>' instruction, the
'<a href="#i_br"><tt>br</tt></a>' instruction, the
'<a href="#i_switch"><tt>switch</tt></a>' instruction, the
+ '<a href="#i_indbr">'<tt>indbr</tt>' Instruction, the
'<a href="#i_invoke"><tt>invoke</tt></a>' instruction, the
'<a href="#i_unwind"><tt>unwind</tt></a>' instruction, and the
'<a href="#i_unreachable"><tt>unreachable</tt></a>' instruction.</p>
@@ -2669,6 +2671,54 @@ IfUnequal:
</div>
+
+<!-- _______________________________________________________________________ -->
+<div class="doc_subsubsection">
+ <a name="i_indbr">'<tt>indbr</tt>' Instruction</a>
+</div>
+
+<div class="doc_text">
+
+<h5>Syntax:</h5>
+<pre>
+ indbr &lt;somety&gt;* &lt;address&gt;, [ label &lt;dest1&gt;, label &lt;dest2&gt;, ... ]
+</pre>
+
+<h5>Overview:</h5>
+
+<p>The '<tt>indbr</tt>' instruction implements an indirect branch to a label
+ within the current function, whose address is specified by
+ "<tt>address</tt>".</p>
+
+<h5>Arguments:</h5>
+
+<p>The '<tt>address</tt>' argument is the address of the label to jump to. The
+ rest of the arguments indicate the full set of possible destinations that the
+ address may point to. Blocks are allowed to occur multiple times in the
+ destination list, though this isn't particularly useful.</p>
+
+<p>This destination list is required so that dataflow analysis has an accurate
+ understanding of the CFG.</p>
+
+<h5>Semantics:</h5>
+
+<p>Control transfers to the block specified in the address argument. All
+ possible destination blocks must be listed in the label list, otherwise this
+ instruction has undefined behavior. This implies that jumps to labels
+ defined in other functions have undefined behavior as well.</p>
+
+<h5>Implementation:</h5>
+
+<p>This is typically implemented with a jump through a register.</p>
+
+<h5>Example:</h5>
+<pre>
+ switch i8* %Addr, [ label %bb1, label %bb2, label %bb3 ]
+</pre>
+
+</div>
+
+
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection">
<a name="i_invoke">'<tt>invoke</tt>' Instruction</a>
diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h
index dccd8e0..55bd256 100644
--- a/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/include/llvm/Bitcode/LLVMBitCodes.h
@@ -209,7 +209,7 @@ namespace bitc {
FUNC_CODE_INST_RET = 10, // RET: [opty,opval<both optional>]
FUNC_CODE_INST_BR = 11, // BR: [bb#, bb#, cond] or [bb#]
- FUNC_CODE_INST_SWITCH = 12, // SWITCH: [opty, opval, n, n x ops]
+ FUNC_CODE_INST_SWITCH = 12, // SWITCH: [opty, operands...]
FUNC_CODE_INST_INVOKE = 13, // INVOKE: [attr, fnty, op0,op1, ...]
FUNC_CODE_INST_UNWIND = 14, // UNWIND
FUNC_CODE_INST_UNREACHABLE = 15, // UNREACHABLE
@@ -236,7 +236,8 @@ namespace bitc {
FUNC_CODE_INST_CMP2 = 28, // CMP2: [opty, opval, opval, pred]
// new select on i1 or [N x i1]
FUNC_CODE_INST_VSELECT = 29, // VSELECT: [ty,opval,opval,predty,pred]
- FUNC_CODE_INST_INBOUNDS_GEP = 30 // INBOUNDS_GEP: [n x operands]
+ FUNC_CODE_INST_INBOUNDS_GEP= 30, // INBOUNDS_GEP: [n x operands]
+ FUNC_CODE_INST_INDBR = 31 // INDBR: [opty, operands...]
};
} // End bitc namespace
} // End llvm namespace
diff --git a/include/llvm/Instruction.def b/include/llvm/Instruction.def
index ec86b35..c0adf40 100644
--- a/include/llvm/Instruction.def
+++ b/include/llvm/Instruction.def
@@ -97,78 +97,79 @@
HANDLE_TERM_INST ( 1, Ret , ReturnInst)
HANDLE_TERM_INST ( 2, Br , BranchInst)
HANDLE_TERM_INST ( 3, Switch , SwitchInst)
-HANDLE_TERM_INST ( 4, Invoke , InvokeInst)
-HANDLE_TERM_INST ( 5, Unwind , UnwindInst)
-HANDLE_TERM_INST ( 6, Unreachable, UnreachableInst)
- LAST_TERM_INST ( 6)
+HANDLE_TERM_INST ( 4, IndBr , IndBrInst)
+HANDLE_TERM_INST ( 5, Invoke , InvokeInst)
+HANDLE_TERM_INST ( 6, Unwind , UnwindInst)
+HANDLE_TERM_INST ( 7, Unreachable, UnreachableInst)
+ LAST_TERM_INST ( 7)
// Standard binary operators...
- FIRST_BINARY_INST( 7)
-HANDLE_BINARY_INST( 7, Add , BinaryOperator)
-HANDLE_BINARY_INST( 8, FAdd , BinaryOperator)
-HANDLE_BINARY_INST( 9, Sub , BinaryOperator)
-HANDLE_BINARY_INST(10, FSub , BinaryOperator)
-HANDLE_BINARY_INST(11, Mul , BinaryOperator)
-HANDLE_BINARY_INST(12, FMul , BinaryOperator)
-HANDLE_BINARY_INST(13, UDiv , BinaryOperator)
-HANDLE_BINARY_INST(14, SDiv , BinaryOperator)
-HANDLE_BINARY_INST(15, FDiv , BinaryOperator)
-HANDLE_BINARY_INST(16, URem , BinaryOperator)
-HANDLE_BINARY_INST(17, SRem , BinaryOperator)
-HANDLE_BINARY_INST(18, FRem , BinaryOperator)
+ FIRST_BINARY_INST( 8)
+HANDLE_BINARY_INST( 8, Add , BinaryOperator)
+HANDLE_BINARY_INST( 9, FAdd , BinaryOperator)
+HANDLE_BINARY_INST(10, Sub , BinaryOperator)
+HANDLE_BINARY_INST(11, FSub , BinaryOperator)
+HANDLE_BINARY_INST(12, Mul , BinaryOperator)
+HANDLE_BINARY_INST(13, FMul , BinaryOperator)
+HANDLE_BINARY_INST(14, UDiv , BinaryOperator)
+HANDLE_BINARY_INST(15, SDiv , BinaryOperator)
+HANDLE_BINARY_INST(16, FDiv , BinaryOperator)
+HANDLE_BINARY_INST(17, URem , BinaryOperator)
+HANDLE_BINARY_INST(18, SRem , BinaryOperator)
+HANDLE_BINARY_INST(19, FRem , BinaryOperator)
// Logical operators (integer operands)
-HANDLE_BINARY_INST(19, Shl , BinaryOperator) // Shift left (logical)
-HANDLE_BINARY_INST(20, LShr , BinaryOperator) // Shift right (logical)
-HANDLE_BINARY_INST(21, AShr , BinaryOperator) // Shift right (arithmetic)
-HANDLE_BINARY_INST(22, And , BinaryOperator)
-HANDLE_BINARY_INST(23, Or , BinaryOperator)
-HANDLE_BINARY_INST(24, Xor , BinaryOperator)
- LAST_BINARY_INST(24)
+HANDLE_BINARY_INST(20, Shl , BinaryOperator) // Shift left (logical)
+HANDLE_BINARY_INST(21, LShr , BinaryOperator) // Shift right (logical)
+HANDLE_BINARY_INST(22, AShr , BinaryOperator) // Shift right (arithmetic)
+HANDLE_BINARY_INST(23, And , BinaryOperator)
+HANDLE_BINARY_INST(24, Or , BinaryOperator)
+HANDLE_BINARY_INST(25, Xor , BinaryOperator)
+ LAST_BINARY_INST(25)
// Memory operators...
- FIRST_MEMORY_INST(25)
-HANDLE_MEMORY_INST(25, Alloca, AllocaInst) // Stack management
-HANDLE_MEMORY_INST(26, Load , LoadInst ) // Memory manipulation instrs
-HANDLE_MEMORY_INST(27, Store , StoreInst )
-HANDLE_MEMORY_INST(28, GetElementPtr, GetElementPtrInst)
- LAST_MEMORY_INST(28)
+ FIRST_MEMORY_INST(26)
+HANDLE_MEMORY_INST(26, Alloca, AllocaInst) // Stack management
+HANDLE_MEMORY_INST(27, Load , LoadInst ) // Memory manipulation instrs
+HANDLE_MEMORY_INST(28, Store , StoreInst )
+HANDLE_MEMORY_INST(29, GetElementPtr, GetElementPtrInst)
+ LAST_MEMORY_INST(29)
// Cast operators ...
// NOTE: The order matters here because CastInst::isEliminableCastPair
// NOTE: (see Instructions.cpp) encodes a table based on this ordering.
- FIRST_CAST_INST(29)
-HANDLE_CAST_INST(29, Trunc , TruncInst ) // Truncate integers
-HANDLE_CAST_INST(30, ZExt , ZExtInst ) // Zero extend integers
-HANDLE_CAST_INST(31, SExt , SExtInst ) // Sign extend integers
-HANDLE_CAST_INST(32, FPToUI , FPToUIInst ) // floating point -> UInt
-HANDLE_CAST_INST(33, FPToSI , FPToSIInst ) // floating point -> SInt
-HANDLE_CAST_INST(34, UIToFP , UIToFPInst ) // UInt -> floating point
-HANDLE_CAST_INST(35, SIToFP , SIToFPInst ) // SInt -> floating point
-HANDLE_CAST_INST(36, FPTrunc , FPTruncInst ) // Truncate floating point
-HANDLE_CAST_INST(37, FPExt , FPExtInst ) // Extend floating point
-HANDLE_CAST_INST(38, PtrToInt, PtrToIntInst) // Pointer -> Integer
-HANDLE_CAST_INST(39, IntToPtr, IntToPtrInst) // Integer -> Pointer
-HANDLE_CAST_INST(40, BitCast , BitCastInst ) // Type cast
- LAST_CAST_INST(40)
+ FIRST_CAST_INST(30)
+HANDLE_CAST_INST(30, Trunc , TruncInst ) // Truncate integers
+HANDLE_CAST_INST(31, ZExt , ZExtInst ) // Zero extend integers
+HANDLE_CAST_INST(32, SExt , SExtInst ) // Sign extend integers
+HANDLE_CAST_INST(33, FPToUI , FPToUIInst ) // floating point -> UInt
+HANDLE_CAST_INST(34, FPToSI , FPToSIInst ) // floating point -> SInt
+HANDLE_CAST_INST(35, UIToFP , UIToFPInst ) // UInt -> floating point
+HANDLE_CAST_INST(36, SIToFP , SIToFPInst ) // SInt -> floating point
+HANDLE_CAST_INST(37, FPTrunc , FPTruncInst ) // Truncate floating point
+HANDLE_CAST_INST(38, FPExt , FPExtInst ) // Extend floating point
+HANDLE_CAST_INST(39, PtrToInt, PtrToIntInst) // Pointer -> Integer
+HANDLE_CAST_INST(40, IntToPtr, IntToPtrInst) // Integer -> Pointer
+HANDLE_CAST_INST(41, BitCast , BitCastInst ) // Type cast
+ LAST_CAST_INST(41)
// Other operators...
- FIRST_OTHER_INST(41)
-HANDLE_OTHER_INST(41, ICmp , ICmpInst ) // Integer comparison instruction
-HANDLE_OTHER_INST(42, FCmp , FCmpInst ) // Floating point comparison instr.
-HANDLE_OTHER_INST(43, PHI , PHINode ) // PHI node instruction
-HANDLE_OTHER_INST(44, Call , CallInst ) // Call a function
-HANDLE_OTHER_INST(45, Select , SelectInst ) // select instruction
-HANDLE_OTHER_INST(46, UserOp1, Instruction) // May be used internally in a pass
-HANDLE_OTHER_INST(47, UserOp2, Instruction) // Internal to passes only
-HANDLE_OTHER_INST(48, VAArg , VAArgInst ) // vaarg instruction
-HANDLE_OTHER_INST(49, ExtractElement, ExtractElementInst)// extract from vector
-HANDLE_OTHER_INST(50, InsertElement, InsertElementInst) // insert into vector
-HANDLE_OTHER_INST(51, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
-HANDLE_OTHER_INST(52, ExtractValue, ExtractValueInst)// extract from aggregate
-HANDLE_OTHER_INST(53, InsertValue, InsertValueInst) // insert into aggregate
-
- LAST_OTHER_INST(53)
+ FIRST_OTHER_INST(42)
+HANDLE_OTHER_INST(42, ICmp , ICmpInst ) // Integer comparison instruction
+HANDLE_OTHER_INST(43, FCmp , FCmpInst ) // Floating point comparison instr.
+HANDLE_OTHER_INST(44, PHI , PHINode ) // PHI node instruction
+HANDLE_OTHER_INST(45, Call , CallInst ) // Call a function
+HANDLE_OTHER_INST(46, Select , SelectInst ) // select instruction
+HANDLE_OTHER_INST(47, UserOp1, Instruction) // May be used internally in a pass
+HANDLE_OTHER_INST(48, UserOp2, Instruction) // Internal to passes only
+HANDLE_OTHER_INST(49, VAArg , VAArgInst ) // vaarg instruction
+HANDLE_OTHER_INST(50, ExtractElement, ExtractElementInst)// extract from vector
+HANDLE_OTHER_INST(51, InsertElement, InsertElementInst) // insert into vector
+HANDLE_OTHER_INST(52, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
+HANDLE_OTHER_INST(53, ExtractValue, ExtractValueInst)// extract from aggregate
+HANDLE_OTHER_INST(54, InsertValue, InsertValueInst) // insert into aggregate
+
+ LAST_OTHER_INST(54)
#undef FIRST_TERM_INST
#undef HANDLE_TERM_INST
diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h
index 2f69171..9a9d718 100644
--- a/include/llvm/Instructions.h
+++ b/include/llvm/Instructions.h
@@ -2076,7 +2076,7 @@ class SwitchInst : public TerminatorInst {
// Operand[1] = Default basic block destination
// Operand[2n ] = Value to match
// Operand[2n+1] = BasicBlock to go to on match
- SwitchInst(const SwitchInst &RI);
+ SwitchInst(const SwitchInst &SI);
void init(Value *Value, BasicBlock *Default, unsigned NumCases);
void resizeOperands(unsigned No);
// allocate space for exactly zero operands
@@ -2088,7 +2088,7 @@ class SwitchInst : public TerminatorInst {
/// be specified here to make memory allocation more efficient. This
/// constructor can also autoinsert before another instruction.
SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases,
- Instruction *InsertBefore = 0);
+ Instruction *InsertBefore);
/// SwitchInst ctor - Create a new switch instruction, specifying a value to
/// switch on and a default destination. The number of additional cases can
@@ -2214,6 +2214,105 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SwitchInst, Value)
//===----------------------------------------------------------------------===//
+// IndBrInst Class
+//===----------------------------------------------------------------------===//
+
+//===---------------------------------------------------------------------------
+/// IndBrInst - Indirect Branch Instruction.
+///
+class IndBrInst : public TerminatorInst {
+ void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
+ unsigned ReservedSpace;
+ // Operand[0] = Value to switch on
+ // Operand[1] = Default basic block destination
+ // Operand[2n ] = Value to match
+ // Operand[2n+1] = BasicBlock to go to on match
+ IndBrInst(const IndBrInst &IBI);
+ void init(Value *Address, unsigned NumDests);
+ void resizeOperands(unsigned No);
+ // allocate space for exactly zero operands
+ void *operator new(size_t s) {
+ return User::operator new(s, 0);
+ }
+ /// IndBrInst ctor - Create a new indbr instruction, specifying an Address to
+ /// jump to. The number of expected destinations can be specified here to
+ /// make memory allocation more efficient. This constructor can also
+ /// autoinsert before another instruction.
+ IndBrInst(Value *Address, unsigned NumDests, Instruction *InsertBefore);
+
+ /// IndBrInst ctor - Create a new indbr instruction, specifying an Address to
+ /// jump to. The number of expected destinations can be specified here to
+ /// make memory allocation more efficient. This constructor also autoinserts
+ /// at the end of the specified BasicBlock.
+ IndBrInst(Value *Address, unsigned NumDests, BasicBlock *InsertAtEnd);
+public:
+ static IndBrInst *Create(Value *Address, unsigned NumDests,
+ Instruction *InsertBefore = 0) {
+ return new IndBrInst(Address, NumDests, InsertBefore);
+ }
+ static IndBrInst *Create(Value *Address, unsigned NumDests,
+ BasicBlock *InsertAtEnd) {
+ return new IndBrInst(Address, NumDests, InsertAtEnd);
+ }
+ ~IndBrInst();
+
+ /// Provide fast operand accessors.
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
+ // Accessor Methods for IndBr instruction.
+ Value *getAddress() { return getOperand(0); }
+ const Value *getAddress() const { return getOperand(0); }
+ void setAddress(Value *V) { setOperand(0, V); }
+
+
+ /// getNumDestinations - return the number of possible destinations in this
+ /// indbr instruction.
+ unsigned getNumDestinations() const { return getNumOperands()-1; }
+
+ /// getDestination - Return the specified destination.
+ BasicBlock *getDestination(unsigned i) { return getSuccessor(i); }
+ const BasicBlock *getDestination(unsigned i) const { return getSuccessor(i); }
+
+ /// addDestination - Add a destination.
+ ///
+ void addDestination(BasicBlock *Dest);
+
+ /// removeDestination - This method removes the specified successor from the
+ /// indbr instruction.
+ void removeDestination(unsigned i);
+
+ virtual IndBrInst *clone() const;
+
+ unsigned getNumSuccessors() const { return getNumOperands()-1; }
+ BasicBlock *getSuccessor(unsigned i) const {
+ return cast<BasicBlock>(getOperand(i+1));
+ }
+ void setSuccessor(unsigned i, BasicBlock *NewSucc) {
+ setOperand(i+1, (Value*)NewSucc);
+ }
+
+ // Methods for support type inquiry through isa, cast, and dyn_cast:
+ static inline bool classof(const IndBrInst *) { return true; }
+ static inline bool classof(const Instruction *I) {
+ return I->getOpcode() == Instruction::IndBr;
+ }
+ static inline bool classof(const Value *V) {
+ return isa<Instruction>(V) && classof(cast<Instruction>(V));
+ }
+private:
+ virtual BasicBlock *getSuccessorV(unsigned idx) const;
+ virtual unsigned getNumSuccessorsV() const;
+ virtual void setSuccessorV(unsigned idx, BasicBlock *B);
+};
+
+template <>
+struct OperandTraits<IndBrInst> : public HungoffOperandTraits<1> {
+};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndBrInst, Value)
+
+
+//===----------------------------------------------------------------------===//
// InvokeInst Class
//===----------------------------------------------------------------------===//
diff --git a/include/llvm/Support/InstVisitor.h b/include/llvm/Support/InstVisitor.h
index ae35a3c..ce97884 100644
--- a/include/llvm/Support/InstVisitor.h
+++ b/include/llvm/Support/InstVisitor.h
@@ -160,6 +160,7 @@ public:
RetTy visitReturnInst(ReturnInst &I) { DELEGATE(TerminatorInst);}
RetTy visitBranchInst(BranchInst &I) { DELEGATE(TerminatorInst);}
RetTy visitSwitchInst(SwitchInst &I) { DELEGATE(TerminatorInst);}
+ RetTy visitIndBrInst(IndBrInst &I) { DELEGATE(TerminatorInst);}
RetTy visitInvokeInst(InvokeInst &I) { DELEGATE(TerminatorInst);}
RetTy visitUnwindInst(UnwindInst &I) { DELEGATE(TerminatorInst);}
RetTy visitUnreachableInst(UnreachableInst &I) { DELEGATE(TerminatorInst);}
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index 4fb7ea9..1003907 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -645,6 +645,7 @@ lltok::Kind LLLexer::LexIdentifier() {
INSTKEYWORD(ret, Ret);
INSTKEYWORD(br, Br);
INSTKEYWORD(switch, Switch);
+ INSTKEYWORD(indbr, IndBr);
INSTKEYWORD(invoke, Invoke);
INSTKEYWORD(unwind, Unwind);
INSTKEYWORD(unreachable, Unreachable);
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index fa803bb..cf16e42 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -2412,6 +2412,18 @@ bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState &PFS) {
ParseValue(T, V, PFS);
}
+bool LLParser::ParseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc,
+ PerFunctionState &PFS) {
+ Value *V;
+ Loc = Lex.getLoc();
+ if (ParseTypeAndValue(V, PFS)) return true;
+ if (!isa<BasicBlock>(V))
+ return Error(Loc, "expected a basic block");
+ BB = cast<BasicBlock>(V);
+ return false;
+}
+
+
/// FunctionHeader
/// ::= OptionalLinkage OptionalVisibility OptionalCallingConv OptRetAttrs
/// Type GlobalName '(' ArgList ')' OptFuncAttrs OptSection
@@ -2719,6 +2731,7 @@ bool LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
case lltok::kw_ret: return ParseRet(Inst, BB, PFS);
case lltok::kw_br: return ParseBr(Inst, PFS);
case lltok::kw_switch: return ParseSwitch(Inst, PFS);
+ case lltok::kw_indbr: return ParseIndBr(Inst, PFS);
case lltok::kw_invoke: return ParseInvoke(Inst, PFS);
// Binary Operators.
case lltok::kw_add:
@@ -2922,7 +2935,8 @@ bool LLParser::ParseRet(Instruction *&Inst, BasicBlock *BB,
/// ::= 'br' TypeAndValue ',' TypeAndValue ',' TypeAndValue
bool LLParser::ParseBr(Instruction *&Inst, PerFunctionState &PFS) {
LocTy Loc, Loc2;
- Value *Op0, *Op1, *Op2;
+ Value *Op0;
+ BasicBlock *Op1, *Op2;
if (ParseTypeAndValue(Op0, Loc, PFS)) return true;
if (BasicBlock *BB = dyn_cast<BasicBlock>(Op0)) {
@@ -2934,17 +2948,12 @@ bool LLParser::ParseBr(Instruction *&Inst, PerFunctionState &PFS) {
return Error(Loc, "branch condition must have 'i1' type");
if (ParseToken(lltok::comma, "expected ',' after branch condition") ||
- ParseTypeAndValue(Op1, Loc, PFS) ||
+ ParseTypeAndBasicBlock(Op1, Loc, PFS) ||
ParseToken(lltok::comma, "expected ',' after true destination") ||
- ParseTypeAndValue(Op2, Loc2, PFS))
+ ParseTypeAndBasicBlock(Op2, Loc2, PFS))
return true;
- if (!isa<BasicBlock>(Op1))
- return Error(Loc, "true destination of branch must be a basic block");
- if (!isa<BasicBlock>(Op2))
- return Error(Loc2, "true destination of branch must be a basic block");
-
- Inst = BranchInst::Create(cast<BasicBlock>(Op1), cast<BasicBlock>(Op2), Op0);
+ Inst = BranchInst::Create(Op1, Op2, Op0);
return false;
}
@@ -2955,50 +2964,87 @@ bool LLParser::ParseBr(Instruction *&Inst, PerFunctionState &PFS) {
/// ::= (TypeAndValue ',' TypeAndValue)*
bool LLParser::ParseSwitch(Instruction *&Inst, PerFunctionState &PFS) {
LocTy CondLoc, BBLoc;
- Value *Cond, *DefaultBB;
+ Value *Cond;
+ BasicBlock *DefaultBB;
if (ParseTypeAndValue(Cond, CondLoc, PFS) ||
ParseToken(lltok::comma, "expected ',' after switch condition") ||
- ParseTypeAndValue(DefaultBB, BBLoc, PFS) ||
+ ParseTypeAndBasicBlock(DefaultBB, BBLoc, PFS) ||
ParseToken(lltok::lsquare, "expected '[' with switch table"))
return true;
if (!isa<IntegerType>(Cond->getType()))
return Error(CondLoc, "switch condition must have integer type");
- if (!isa<BasicBlock>(DefaultBB))
- return Error(BBLoc, "default destination must be a basic block");
// Parse the jump table pairs.
SmallPtrSet<Value*, 32> SeenCases;
SmallVector<std::pair<ConstantInt*, BasicBlock*>, 32> Table;
while (Lex.getKind() != lltok::rsquare) {
- Value *Constant, *DestBB;
+ Value *Constant;
+ BasicBlock *DestBB;
if (ParseTypeAndValue(Constant, CondLoc, PFS) ||
ParseToken(lltok::comma, "expected ',' after case value") ||
- ParseTypeAndValue(DestBB, BBLoc, PFS))
+ ParseTypeAndBasicBlock(DestBB, PFS))
return true;
-
+
if (!SeenCases.insert(Constant))
return Error(CondLoc, "duplicate case value in switch");
if (!isa<ConstantInt>(Constant))
return Error(CondLoc, "case value is not a constant integer");
- if (!isa<BasicBlock>(DestBB))
- return Error(BBLoc, "case destination is not a basic block");
- Table.push_back(std::make_pair(cast<ConstantInt>(Constant),
- cast<BasicBlock>(DestBB)));
+ Table.push_back(std::make_pair(cast<ConstantInt>(Constant), DestBB));
}
Lex.Lex(); // Eat the ']'.
- SwitchInst *SI = SwitchInst::Create(Cond, cast<BasicBlock>(DefaultBB),
- Table.size());
+ SwitchInst *SI = SwitchInst::Create(Cond, DefaultBB, Table.size());
for (unsigned i = 0, e = Table.size(); i != e; ++i)
SI->addCase(Table[i].first, Table[i].second);
Inst = SI;
return false;
}
+/// ParseIndBr
+/// Instruction
+/// ::= 'indbr' TypeAndValue ',' '[' LabelList ']'
+bool LLParser::ParseIndBr(Instruction *&Inst, PerFunctionState &PFS) {
+ LocTy AddrLoc;
+ Value *Address;
+ if (ParseTypeAndValue(Address, AddrLoc, PFS) ||
+ ParseToken(lltok::comma, "expected ',' after indbr address") ||
+ ParseToken(lltok::lsquare, "expected '[' with indbr"))
+ return true;
+
+ if (!isa<PointerType>(Address->getType()))
+ return Error(AddrLoc, "indbr address must have pointer type");
+
+ // Parse the destination list.
+ SmallVector<BasicBlock*, 16> DestList;
+
+ if (Lex.getKind() != lltok::rsquare) {
+ BasicBlock *DestBB;
+ if (ParseTypeAndBasicBlock(DestBB, PFS))
+ return true;
+ DestList.push_back(DestBB);
+
+ while (EatIfPresent(lltok::comma)) {
+ if (ParseTypeAndBasicBlock(DestBB, PFS))
+ return true;
+ DestList.push_back(DestBB);
+ }
+ }
+
+ if (ParseToken(lltok::rsquare, "expected ']' at end of block list"))
+ return true;
+
+ IndBrInst *IBI = IndBrInst::Create(Address, DestList.size());
+ for (unsigned i = 0, e = DestList.size(); i != e; ++i)
+ IBI->addDestination(DestList[i]);
+ Inst = IBI;
+ return false;
+}
+
+
/// ParseInvoke
/// ::= 'invoke' OptionalCallingConv OptionalAttrs Type Value ParamList
/// OptionalAttrs 'to' TypeAndValue 'unwind' TypeAndValue
@@ -3011,7 +3057,7 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) {
ValID CalleeID;
SmallVector<ParamInfo, 16> ArgList;
- Value *NormalBB, *UnwindBB;
+ BasicBlock *NormalBB, *UnwindBB;
if (ParseOptionalCallingConv(CC) ||
ParseOptionalAttrs(RetAttrs, 1) ||
ParseType(RetType, RetTypeLoc, true /*void allowed*/) ||
@@ -3019,16 +3065,11 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) {
ParseParameterList(ArgList, PFS) ||
ParseOptionalAttrs(FnAttrs, 2) ||
ParseToken(lltok::kw_to, "expected 'to' in invoke") ||
- ParseTypeAndValue(NormalBB, PFS) ||
+ ParseTypeAndBasicBlock(NormalBB, PFS) ||
ParseToken(lltok::kw_unwind, "expected 'unwind' in invoke") ||
- ParseTypeAndValue(UnwindBB, PFS))
+ ParseTypeAndBasicBlock(UnwindBB, PFS))
return true;
- if (!isa<BasicBlock>(NormalBB))
- return Error(CallLoc, "normal destination is not a basic block");
- if (!isa<BasicBlock>(UnwindBB))
- return Error(CallLoc, "unwind destination is not a basic block");
-
// If RetType is a non-function pointer type, then this is the short syntax
// for the call, which means that RetType is just the return type. Infer the
// rest of the function argument types from the arguments that are present.
@@ -3096,8 +3137,7 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) {
// Finish off the Attributes and check them
AttrListPtr PAL = AttrListPtr::get(Attrs.begin(), Attrs.end());
- InvokeInst *II = InvokeInst::Create(Callee, cast<BasicBlock>(NormalBB),
- cast<BasicBlock>(UnwindBB),
+ InvokeInst *II = InvokeInst::Create(Callee, NormalBB, UnwindBB,
Args.begin(), Args.end());
II->setCallingConv(CC);
II->setAttributes(PAL);
diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h
index b6877bc..37473a0 100644
--- a/lib/AsmParser/LLParser.h
+++ b/lib/AsmParser/LLParser.h
@@ -230,7 +230,13 @@ namespace llvm {
Loc = Lex.getLoc();
return ParseTypeAndValue(V, PFS);
}
-
+ bool ParseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc,
+ PerFunctionState &PFS);
+ bool ParseTypeAndBasicBlock(BasicBlock *&BB, PerFunctionState &PFS) {
+ LocTy Loc;
+ return ParseTypeAndBasicBlock(BB, Loc, PFS);
+ }
+
struct ParamInfo {
LocTy Loc;
Value *V;
@@ -264,6 +270,7 @@ namespace llvm {
bool ParseRet(Instruction *&Inst, BasicBlock *BB, PerFunctionState &PFS);
bool ParseBr(Instruction *&Inst, PerFunctionState &PFS);
bool ParseSwitch(Instruction *&Inst, PerFunctionState &PFS);
+ bool ParseIndBr(Instruction *&Inst, PerFunctionState &PFS);
bool ParseInvoke(Instruction *&Inst, PerFunctionState &PFS);
bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc,
diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h
index f5072fe..a25b6f0 100644
--- a/lib/AsmParser/LLToken.h
+++ b/lib/AsmParser/LLToken.h
@@ -111,7 +111,7 @@ namespace lltok {
kw_fptoui, kw_fptosi, kw_inttoptr, kw_ptrtoint, kw_bitcast,
kw_select, kw_va_arg,
- kw_ret, kw_br, kw_switch, kw_invoke, kw_unwind, kw_unreachable,
+ kw_ret, kw_br, kw_switch, kw_indbr, kw_invoke, kw_unwind, kw_unreachable,
kw_malloc, kw_alloca, kw_free, kw_load, kw_store, kw_getelementptr,
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index b392122..41803c0 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -1951,7 +1951,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
}
break;
}
- case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, opval, n, n x ops]
+ case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...]
if (Record.size() < 3 || (Record.size() & 1) == 0)
return Error("Invalid SWITCH record");
const Type *OpTy = getTypeByID(Record[0]);
@@ -1975,7 +1975,28 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
I = SI;
break;
}
-
+ case bitc::FUNC_CODE_INST_INDBR: { // INDBR: [opty, op0, op1, ...]
+ if (Record.size() < 2)
+ return Error("Invalid INDBR record");
+ const Type *OpTy = getTypeByID(Record[0]);
+ Value *Address = getFnValueByID(Record[1], OpTy);
+ if (OpTy == 0 || Address == 0)
+ return Error("Invalid INDBR record");
+ unsigned NumDests = Record.size()-2;
+ IndBrInst *IBI = IndBrInst::Create(Address, NumDests);
+ InstructionList.push_back(IBI);
+ for (unsigned i = 0, e = NumDests; i != e; ++i) {
+ if (BasicBlock *DestBB = getBasicBlock(Record[2+i])) {
+ IBI->addDestination(DestBB);
+ } else {
+ delete IBI;
+ return Error("Invalid INDBR record!");
+ }
+ }
+ I = IBI;
+ break;
+ }
+
case bitc::FUNC_CODE_INST_INVOKE: {
// INVOKE: [attrs, cc, normBB, unwindBB, fnty, op0,op1,op2, ...]
if (Record.size() < 4) return Error("Invalid INVOKE record");
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index aee825c..c0f97c1 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1001,7 +1001,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
case Instruction::Br:
{
Code = bitc::FUNC_CODE_INST_BR;
- BranchInst &II(cast<BranchInst>(I));
+ BranchInst &II = cast<BranchInst>(I);
Vals.push_back(VE.getValueID(II.getSuccessor(0)));
if (II.isConditional()) {
Vals.push_back(VE.getValueID(II.getSuccessor(1)));
@@ -1015,6 +1015,13 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
Vals.push_back(VE.getValueID(I.getOperand(i)));
break;
+ case Instruction::IndBr:
+ Code = bitc::FUNC_CODE_INST_INDBR;
+ Vals.push_back(VE.getTypeID(I.getOperand(0)->getType()));
+ for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
+ Vals.push_back(VE.getValueID(I.getOperand(i)));
+ break;
+
case Instruction::Invoke: {
const InvokeInst *II = cast<InvokeInst>(&I);
const Value *Callee(II->getCalledValue());
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
index b220d55..73c9c5f 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
@@ -2131,6 +2131,11 @@ void SelectionDAGLowering::visitSwitch(SwitchInst &SI) {
}
}
+void SelectionDAGLowering::visitIndBr(IndBrInst &I) {
+ fprintf(stderr, "indbr codegen not implemented yet");
+ abort();
+}
+
void SelectionDAGLowering::visitFSub(User &I) {
// -0.0 - X --> fneg
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h
index 7470551..9aca707 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h
@@ -49,6 +49,7 @@ class GetElementPtrInst;
class GCFunctionInfo;
class ICmpInst;
class IntToPtrInst;
+class IndBrInst;
class InvokeInst;
class InsertElementInst;
class InsertValueInst;
@@ -448,6 +449,7 @@ private:
void visitRet(ReturnInst &I);
void visitBr(BranchInst &I);
void visitSwitch(SwitchInst &I);
+ void visitIndBr(IndBrInst &I);
void visitUnreachable(UnreachableInst &I) { /* noop */ }
// Helpers for visitSwitch
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;
diff --git a/test/Feature/terminators.ll b/test/Feature/terminators.ll
index 417f56b..d1b9710 100644
--- a/test/Feature/terminators.ll
+++ b/test/Feature/terminators.ll
@@ -24,3 +24,14 @@ Case4: ; preds = %0
ret i32 16
}
+
+
+define i32 @indbrtest(i8* %P, i32* %Q) {
+ indbr i8* %P, [label %BB1, label %BB2, label %BB3]
+BB1:
+ indbr i32* %Q, []
+BB2:
+ indbr i32* %Q, [label %BB1, label %BB2]
+BB3:
+ ret i32 2
+}