<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>
'<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>
</div>
+
+<!-- _______________________________________________________________________ -->
+<div class="doc_subsubsection">
+ <a name="i_indbr">'<tt>indbr</tt>' Instruction</a>
+</div>
+
+<div class="doc_text">
+
+<h5>Syntax:</h5>
+<pre>
+ indbr <somety>* <address>, [ label <dest1>, label <dest2>, ... ]
+</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>
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
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
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
// 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
/// 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
//===----------------------------------------------------------------------===//
+// 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
//===----------------------------------------------------------------------===//
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);}
INSTKEYWORD(ret, Ret);
INSTKEYWORD(br, Br);
INSTKEYWORD(switch, Switch);
+ INSTKEYWORD(indbr, IndBr);
INSTKEYWORD(invoke, Invoke);
INSTKEYWORD(unwind, Unwind);
INSTKEYWORD(unreachable, Unreachable);
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
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:
/// ::= '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)) {
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;
}
/// ::= (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
ValID CalleeID;
SmallVector<ParamInfo, 16> ArgList;
- Value *NormalBB, *UnwindBB;
+ BasicBlock *NormalBB, *UnwindBB;
if (ParseOptionalCallingConv(CC) ||
ParseOptionalAttrs(RetAttrs, 1) ||
ParseType(RetType, RetTypeLoc, true /*void allowed*/) ||
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.
// 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);
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;
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,
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,
}
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]);
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");
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)));
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());
}
}
+void SelectionDAGLowering::visitIndBr(IndBrInst &I) {
+ fprintf(stderr, "indbr codegen not implemented yet");
+ abort();
+}
+
void SelectionDAGLowering::visitFSub(User &I) {
// -0.0 - X --> fneg
class GCFunctionInfo;
class ICmpInst;
class IntToPtrInst;
+class IndBrInst;
class InvokeInst;
class InsertElementInst;
class InsertValueInst;
void visitRet(ReturnInst &I);
void visitBr(BranchInst &I);
void visitSwitch(SwitchInst &I);
+ void visitIndBr(IndBrInst &I);
void visitUnreachable(UnreachableInst &I) { /* noop */ }
// Helpers for visitSwitch
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 << ", ";
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);
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";
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.
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;
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
+}