forked from OSchip/llvm-project
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. llvm-svn: 85274
This commit is contained in:
parent
df5dcdaa10
commit
3ed871fe62
|
@ -110,6 +110,7 @@
|
||||||
<li><a href="#i_ret">'<tt>ret</tt>' Instruction</a></li>
|
<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_br">'<tt>br</tt>' Instruction</a></li>
|
||||||
<li><a href="#i_switch">'<tt>switch</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_invoke">'<tt>invoke</tt>' Instruction</a></li>
|
||||||
<li><a href="#i_unwind">'<tt>unwind</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>
|
<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_ret"><tt>ret</tt></a>' instruction, the
|
||||||
'<a href="#i_br"><tt>br</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_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_invoke"><tt>invoke</tt></a>' instruction, the
|
||||||
'<a href="#i_unwind"><tt>unwind</tt></a>' instruction, and the
|
'<a href="#i_unwind"><tt>unwind</tt></a>' instruction, and the
|
||||||
'<a href="#i_unreachable"><tt>unreachable</tt></a>' instruction.</p>
|
'<a href="#i_unreachable"><tt>unreachable</tt></a>' instruction.</p>
|
||||||
|
@ -2669,6 +2671,54 @@ IfUnequal:
|
||||||
|
|
||||||
</div>
|
</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">
|
<div class="doc_subsubsection">
|
||||||
<a name="i_invoke">'<tt>invoke</tt>' Instruction</a>
|
<a name="i_invoke">'<tt>invoke</tt>' Instruction</a>
|
||||||
|
|
|
@ -209,7 +209,7 @@ namespace bitc {
|
||||||
|
|
||||||
FUNC_CODE_INST_RET = 10, // RET: [opty,opval<both optional>]
|
FUNC_CODE_INST_RET = 10, // RET: [opty,opval<both optional>]
|
||||||
FUNC_CODE_INST_BR = 11, // BR: [bb#, bb#, cond] or [bb#]
|
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_INVOKE = 13, // INVOKE: [attr, fnty, op0,op1, ...]
|
||||||
FUNC_CODE_INST_UNWIND = 14, // UNWIND
|
FUNC_CODE_INST_UNWIND = 14, // UNWIND
|
||||||
FUNC_CODE_INST_UNREACHABLE = 15, // UNREACHABLE
|
FUNC_CODE_INST_UNREACHABLE = 15, // UNREACHABLE
|
||||||
|
@ -236,7 +236,8 @@ namespace bitc {
|
||||||
FUNC_CODE_INST_CMP2 = 28, // CMP2: [opty, opval, opval, pred]
|
FUNC_CODE_INST_CMP2 = 28, // CMP2: [opty, opval, opval, pred]
|
||||||
// new select on i1 or [N x i1]
|
// new select on i1 or [N x i1]
|
||||||
FUNC_CODE_INST_VSELECT = 29, // VSELECT: [ty,opval,opval,predty,pred]
|
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 bitc namespace
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
|
|
@ -97,78 +97,79 @@
|
||||||
HANDLE_TERM_INST ( 1, Ret , ReturnInst)
|
HANDLE_TERM_INST ( 1, Ret , ReturnInst)
|
||||||
HANDLE_TERM_INST ( 2, Br , BranchInst)
|
HANDLE_TERM_INST ( 2, Br , BranchInst)
|
||||||
HANDLE_TERM_INST ( 3, Switch , SwitchInst)
|
HANDLE_TERM_INST ( 3, Switch , SwitchInst)
|
||||||
HANDLE_TERM_INST ( 4, Invoke , InvokeInst)
|
HANDLE_TERM_INST ( 4, IndBr , IndBrInst)
|
||||||
HANDLE_TERM_INST ( 5, Unwind , UnwindInst)
|
HANDLE_TERM_INST ( 5, Invoke , InvokeInst)
|
||||||
HANDLE_TERM_INST ( 6, Unreachable, UnreachableInst)
|
HANDLE_TERM_INST ( 6, Unwind , UnwindInst)
|
||||||
LAST_TERM_INST ( 6)
|
HANDLE_TERM_INST ( 7, Unreachable, UnreachableInst)
|
||||||
|
LAST_TERM_INST ( 7)
|
||||||
|
|
||||||
// Standard binary operators...
|
// Standard binary operators...
|
||||||
FIRST_BINARY_INST( 7)
|
FIRST_BINARY_INST( 8)
|
||||||
HANDLE_BINARY_INST( 7, Add , BinaryOperator)
|
HANDLE_BINARY_INST( 8, Add , BinaryOperator)
|
||||||
HANDLE_BINARY_INST( 8, FAdd , BinaryOperator)
|
HANDLE_BINARY_INST( 9, FAdd , BinaryOperator)
|
||||||
HANDLE_BINARY_INST( 9, Sub , BinaryOperator)
|
HANDLE_BINARY_INST(10, Sub , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(10, FSub , BinaryOperator)
|
HANDLE_BINARY_INST(11, FSub , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(11, Mul , BinaryOperator)
|
HANDLE_BINARY_INST(12, Mul , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(12, FMul , BinaryOperator)
|
HANDLE_BINARY_INST(13, FMul , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(13, UDiv , BinaryOperator)
|
HANDLE_BINARY_INST(14, UDiv , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(14, SDiv , BinaryOperator)
|
HANDLE_BINARY_INST(15, SDiv , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(15, FDiv , BinaryOperator)
|
HANDLE_BINARY_INST(16, FDiv , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(16, URem , BinaryOperator)
|
HANDLE_BINARY_INST(17, URem , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(17, SRem , BinaryOperator)
|
HANDLE_BINARY_INST(18, SRem , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(18, FRem , BinaryOperator)
|
HANDLE_BINARY_INST(19, FRem , BinaryOperator)
|
||||||
|
|
||||||
// Logical operators (integer operands)
|
// Logical operators (integer operands)
|
||||||
HANDLE_BINARY_INST(19, Shl , BinaryOperator) // Shift left (logical)
|
HANDLE_BINARY_INST(20, Shl , BinaryOperator) // Shift left (logical)
|
||||||
HANDLE_BINARY_INST(20, LShr , BinaryOperator) // Shift right (logical)
|
HANDLE_BINARY_INST(21, LShr , BinaryOperator) // Shift right (logical)
|
||||||
HANDLE_BINARY_INST(21, AShr , BinaryOperator) // Shift right (arithmetic)
|
HANDLE_BINARY_INST(22, AShr , BinaryOperator) // Shift right (arithmetic)
|
||||||
HANDLE_BINARY_INST(22, And , BinaryOperator)
|
HANDLE_BINARY_INST(23, And , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(23, Or , BinaryOperator)
|
HANDLE_BINARY_INST(24, Or , BinaryOperator)
|
||||||
HANDLE_BINARY_INST(24, Xor , BinaryOperator)
|
HANDLE_BINARY_INST(25, Xor , BinaryOperator)
|
||||||
LAST_BINARY_INST(24)
|
LAST_BINARY_INST(25)
|
||||||
|
|
||||||
// Memory operators...
|
// Memory operators...
|
||||||
FIRST_MEMORY_INST(25)
|
FIRST_MEMORY_INST(26)
|
||||||
HANDLE_MEMORY_INST(25, Alloca, AllocaInst) // Stack management
|
HANDLE_MEMORY_INST(26, Alloca, AllocaInst) // Stack management
|
||||||
HANDLE_MEMORY_INST(26, Load , LoadInst ) // Memory manipulation instrs
|
HANDLE_MEMORY_INST(27, Load , LoadInst ) // Memory manipulation instrs
|
||||||
HANDLE_MEMORY_INST(27, Store , StoreInst )
|
HANDLE_MEMORY_INST(28, Store , StoreInst )
|
||||||
HANDLE_MEMORY_INST(28, GetElementPtr, GetElementPtrInst)
|
HANDLE_MEMORY_INST(29, GetElementPtr, GetElementPtrInst)
|
||||||
LAST_MEMORY_INST(28)
|
LAST_MEMORY_INST(29)
|
||||||
|
|
||||||
// Cast operators ...
|
// Cast operators ...
|
||||||
// NOTE: The order matters here because CastInst::isEliminableCastPair
|
// NOTE: The order matters here because CastInst::isEliminableCastPair
|
||||||
// NOTE: (see Instructions.cpp) encodes a table based on this ordering.
|
// NOTE: (see Instructions.cpp) encodes a table based on this ordering.
|
||||||
FIRST_CAST_INST(29)
|
FIRST_CAST_INST(30)
|
||||||
HANDLE_CAST_INST(29, Trunc , TruncInst ) // Truncate integers
|
HANDLE_CAST_INST(30, Trunc , TruncInst ) // Truncate integers
|
||||||
HANDLE_CAST_INST(30, ZExt , ZExtInst ) // Zero extend integers
|
HANDLE_CAST_INST(31, ZExt , ZExtInst ) // Zero extend integers
|
||||||
HANDLE_CAST_INST(31, SExt , SExtInst ) // Sign extend integers
|
HANDLE_CAST_INST(32, SExt , SExtInst ) // Sign extend integers
|
||||||
HANDLE_CAST_INST(32, FPToUI , FPToUIInst ) // floating point -> UInt
|
HANDLE_CAST_INST(33, FPToUI , FPToUIInst ) // floating point -> UInt
|
||||||
HANDLE_CAST_INST(33, FPToSI , FPToSIInst ) // floating point -> SInt
|
HANDLE_CAST_INST(34, FPToSI , FPToSIInst ) // floating point -> SInt
|
||||||
HANDLE_CAST_INST(34, UIToFP , UIToFPInst ) // UInt -> floating point
|
HANDLE_CAST_INST(35, UIToFP , UIToFPInst ) // UInt -> floating point
|
||||||
HANDLE_CAST_INST(35, SIToFP , SIToFPInst ) // SInt -> floating point
|
HANDLE_CAST_INST(36, SIToFP , SIToFPInst ) // SInt -> floating point
|
||||||
HANDLE_CAST_INST(36, FPTrunc , FPTruncInst ) // Truncate floating point
|
HANDLE_CAST_INST(37, FPTrunc , FPTruncInst ) // Truncate floating point
|
||||||
HANDLE_CAST_INST(37, FPExt , FPExtInst ) // Extend floating point
|
HANDLE_CAST_INST(38, FPExt , FPExtInst ) // Extend floating point
|
||||||
HANDLE_CAST_INST(38, PtrToInt, PtrToIntInst) // Pointer -> Integer
|
HANDLE_CAST_INST(39, PtrToInt, PtrToIntInst) // Pointer -> Integer
|
||||||
HANDLE_CAST_INST(39, IntToPtr, IntToPtrInst) // Integer -> Pointer
|
HANDLE_CAST_INST(40, IntToPtr, IntToPtrInst) // Integer -> Pointer
|
||||||
HANDLE_CAST_INST(40, BitCast , BitCastInst ) // Type cast
|
HANDLE_CAST_INST(41, BitCast , BitCastInst ) // Type cast
|
||||||
LAST_CAST_INST(40)
|
LAST_CAST_INST(41)
|
||||||
|
|
||||||
// Other operators...
|
// Other operators...
|
||||||
FIRST_OTHER_INST(41)
|
FIRST_OTHER_INST(42)
|
||||||
HANDLE_OTHER_INST(41, ICmp , ICmpInst ) // Integer comparison instruction
|
HANDLE_OTHER_INST(42, ICmp , ICmpInst ) // Integer comparison instruction
|
||||||
HANDLE_OTHER_INST(42, FCmp , FCmpInst ) // Floating point comparison instr.
|
HANDLE_OTHER_INST(43, FCmp , FCmpInst ) // Floating point comparison instr.
|
||||||
HANDLE_OTHER_INST(43, PHI , PHINode ) // PHI node instruction
|
HANDLE_OTHER_INST(44, PHI , PHINode ) // PHI node instruction
|
||||||
HANDLE_OTHER_INST(44, Call , CallInst ) // Call a function
|
HANDLE_OTHER_INST(45, Call , CallInst ) // Call a function
|
||||||
HANDLE_OTHER_INST(45, Select , SelectInst ) // select instruction
|
HANDLE_OTHER_INST(46, Select , SelectInst ) // select instruction
|
||||||
HANDLE_OTHER_INST(46, UserOp1, Instruction) // May be used internally in a pass
|
HANDLE_OTHER_INST(47, UserOp1, Instruction) // May be used internally in a pass
|
||||||
HANDLE_OTHER_INST(47, UserOp2, Instruction) // Internal to passes only
|
HANDLE_OTHER_INST(48, UserOp2, Instruction) // Internal to passes only
|
||||||
HANDLE_OTHER_INST(48, VAArg , VAArgInst ) // vaarg instruction
|
HANDLE_OTHER_INST(49, VAArg , VAArgInst ) // vaarg instruction
|
||||||
HANDLE_OTHER_INST(49, ExtractElement, ExtractElementInst)// extract from vector
|
HANDLE_OTHER_INST(50, ExtractElement, ExtractElementInst)// extract from vector
|
||||||
HANDLE_OTHER_INST(50, InsertElement, InsertElementInst) // insert into vector
|
HANDLE_OTHER_INST(51, InsertElement, InsertElementInst) // insert into vector
|
||||||
HANDLE_OTHER_INST(51, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
|
HANDLE_OTHER_INST(52, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
|
||||||
HANDLE_OTHER_INST(52, ExtractValue, ExtractValueInst)// extract from aggregate
|
HANDLE_OTHER_INST(53, ExtractValue, ExtractValueInst)// extract from aggregate
|
||||||
HANDLE_OTHER_INST(53, InsertValue, InsertValueInst) // insert into aggregate
|
HANDLE_OTHER_INST(54, InsertValue, InsertValueInst) // insert into aggregate
|
||||||
|
|
||||||
LAST_OTHER_INST(53)
|
LAST_OTHER_INST(54)
|
||||||
|
|
||||||
#undef FIRST_TERM_INST
|
#undef FIRST_TERM_INST
|
||||||
#undef HANDLE_TERM_INST
|
#undef HANDLE_TERM_INST
|
||||||
|
|
|
@ -2076,7 +2076,7 @@ class SwitchInst : public TerminatorInst {
|
||||||
// Operand[1] = Default basic block destination
|
// Operand[1] = Default basic block destination
|
||||||
// Operand[2n ] = Value to match
|
// Operand[2n ] = Value to match
|
||||||
// Operand[2n+1] = BasicBlock to go to on 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 init(Value *Value, BasicBlock *Default, unsigned NumCases);
|
||||||
void resizeOperands(unsigned No);
|
void resizeOperands(unsigned No);
|
||||||
// allocate space for exactly zero operands
|
// allocate space for exactly zero operands
|
||||||
|
@ -2088,7 +2088,7 @@ class SwitchInst : public TerminatorInst {
|
||||||
/// be specified here to make memory allocation more efficient. This
|
/// be specified here to make memory allocation more efficient. This
|
||||||
/// constructor can also autoinsert before another instruction.
|
/// constructor can also autoinsert before another instruction.
|
||||||
SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases,
|
SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases,
|
||||||
Instruction *InsertBefore = 0);
|
Instruction *InsertBefore);
|
||||||
|
|
||||||
/// SwitchInst ctor - Create a new switch instruction, specifying a value to
|
/// SwitchInst ctor - Create a new switch instruction, specifying a value to
|
||||||
/// switch on and a default destination. The number of additional cases can
|
/// switch on and a default destination. The number of additional cases can
|
||||||
|
@ -2213,6 +2213,105 @@ struct OperandTraits<SwitchInst> : public HungoffOperandTraits<2> {
|
||||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SwitchInst, Value)
|
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
|
// InvokeInst Class
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -160,6 +160,7 @@ public:
|
||||||
RetTy visitReturnInst(ReturnInst &I) { DELEGATE(TerminatorInst);}
|
RetTy visitReturnInst(ReturnInst &I) { DELEGATE(TerminatorInst);}
|
||||||
RetTy visitBranchInst(BranchInst &I) { DELEGATE(TerminatorInst);}
|
RetTy visitBranchInst(BranchInst &I) { DELEGATE(TerminatorInst);}
|
||||||
RetTy visitSwitchInst(SwitchInst &I) { DELEGATE(TerminatorInst);}
|
RetTy visitSwitchInst(SwitchInst &I) { DELEGATE(TerminatorInst);}
|
||||||
|
RetTy visitIndBrInst(IndBrInst &I) { DELEGATE(TerminatorInst);}
|
||||||
RetTy visitInvokeInst(InvokeInst &I) { DELEGATE(TerminatorInst);}
|
RetTy visitInvokeInst(InvokeInst &I) { DELEGATE(TerminatorInst);}
|
||||||
RetTy visitUnwindInst(UnwindInst &I) { DELEGATE(TerminatorInst);}
|
RetTy visitUnwindInst(UnwindInst &I) { DELEGATE(TerminatorInst);}
|
||||||
RetTy visitUnreachableInst(UnreachableInst &I) { DELEGATE(TerminatorInst);}
|
RetTy visitUnreachableInst(UnreachableInst &I) { DELEGATE(TerminatorInst);}
|
||||||
|
|
|
@ -645,6 +645,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||||
INSTKEYWORD(ret, Ret);
|
INSTKEYWORD(ret, Ret);
|
||||||
INSTKEYWORD(br, Br);
|
INSTKEYWORD(br, Br);
|
||||||
INSTKEYWORD(switch, Switch);
|
INSTKEYWORD(switch, Switch);
|
||||||
|
INSTKEYWORD(indbr, IndBr);
|
||||||
INSTKEYWORD(invoke, Invoke);
|
INSTKEYWORD(invoke, Invoke);
|
||||||
INSTKEYWORD(unwind, Unwind);
|
INSTKEYWORD(unwind, Unwind);
|
||||||
INSTKEYWORD(unreachable, Unreachable);
|
INSTKEYWORD(unreachable, Unreachable);
|
||||||
|
|
|
@ -2412,6 +2412,18 @@ bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState &PFS) {
|
||||||
ParseValue(T, V, 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
|
/// FunctionHeader
|
||||||
/// ::= OptionalLinkage OptionalVisibility OptionalCallingConv OptRetAttrs
|
/// ::= OptionalLinkage OptionalVisibility OptionalCallingConv OptRetAttrs
|
||||||
/// Type GlobalName '(' ArgList ')' OptFuncAttrs OptSection
|
/// 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_ret: return ParseRet(Inst, BB, PFS);
|
||||||
case lltok::kw_br: return ParseBr(Inst, PFS);
|
case lltok::kw_br: return ParseBr(Inst, PFS);
|
||||||
case lltok::kw_switch: return ParseSwitch(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);
|
case lltok::kw_invoke: return ParseInvoke(Inst, PFS);
|
||||||
// Binary Operators.
|
// Binary Operators.
|
||||||
case lltok::kw_add:
|
case lltok::kw_add:
|
||||||
|
@ -2922,7 +2935,8 @@ bool LLParser::ParseRet(Instruction *&Inst, BasicBlock *BB,
|
||||||
/// ::= 'br' TypeAndValue ',' TypeAndValue ',' TypeAndValue
|
/// ::= 'br' TypeAndValue ',' TypeAndValue ',' TypeAndValue
|
||||||
bool LLParser::ParseBr(Instruction *&Inst, PerFunctionState &PFS) {
|
bool LLParser::ParseBr(Instruction *&Inst, PerFunctionState &PFS) {
|
||||||
LocTy Loc, Loc2;
|
LocTy Loc, Loc2;
|
||||||
Value *Op0, *Op1, *Op2;
|
Value *Op0;
|
||||||
|
BasicBlock *Op1, *Op2;
|
||||||
if (ParseTypeAndValue(Op0, Loc, PFS)) return true;
|
if (ParseTypeAndValue(Op0, Loc, PFS)) return true;
|
||||||
|
|
||||||
if (BasicBlock *BB = dyn_cast<BasicBlock>(Op0)) {
|
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");
|
return Error(Loc, "branch condition must have 'i1' type");
|
||||||
|
|
||||||
if (ParseToken(lltok::comma, "expected ',' after branch condition") ||
|
if (ParseToken(lltok::comma, "expected ',' after branch condition") ||
|
||||||
ParseTypeAndValue(Op1, Loc, PFS) ||
|
ParseTypeAndBasicBlock(Op1, Loc, PFS) ||
|
||||||
ParseToken(lltok::comma, "expected ',' after true destination") ||
|
ParseToken(lltok::comma, "expected ',' after true destination") ||
|
||||||
ParseTypeAndValue(Op2, Loc2, PFS))
|
ParseTypeAndBasicBlock(Op2, Loc2, PFS))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!isa<BasicBlock>(Op1))
|
Inst = BranchInst::Create(Op1, Op2, Op0);
|
||||||
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);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2955,50 +2964,87 @@ bool LLParser::ParseBr(Instruction *&Inst, PerFunctionState &PFS) {
|
||||||
/// ::= (TypeAndValue ',' TypeAndValue)*
|
/// ::= (TypeAndValue ',' TypeAndValue)*
|
||||||
bool LLParser::ParseSwitch(Instruction *&Inst, PerFunctionState &PFS) {
|
bool LLParser::ParseSwitch(Instruction *&Inst, PerFunctionState &PFS) {
|
||||||
LocTy CondLoc, BBLoc;
|
LocTy CondLoc, BBLoc;
|
||||||
Value *Cond, *DefaultBB;
|
Value *Cond;
|
||||||
|
BasicBlock *DefaultBB;
|
||||||
if (ParseTypeAndValue(Cond, CondLoc, PFS) ||
|
if (ParseTypeAndValue(Cond, CondLoc, PFS) ||
|
||||||
ParseToken(lltok::comma, "expected ',' after switch condition") ||
|
ParseToken(lltok::comma, "expected ',' after switch condition") ||
|
||||||
ParseTypeAndValue(DefaultBB, BBLoc, PFS) ||
|
ParseTypeAndBasicBlock(DefaultBB, BBLoc, PFS) ||
|
||||||
ParseToken(lltok::lsquare, "expected '[' with switch table"))
|
ParseToken(lltok::lsquare, "expected '[' with switch table"))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!isa<IntegerType>(Cond->getType()))
|
if (!isa<IntegerType>(Cond->getType()))
|
||||||
return Error(CondLoc, "switch condition must have integer type");
|
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.
|
// Parse the jump table pairs.
|
||||||
SmallPtrSet<Value*, 32> SeenCases;
|
SmallPtrSet<Value*, 32> SeenCases;
|
||||||
SmallVector<std::pair<ConstantInt*, BasicBlock*>, 32> Table;
|
SmallVector<std::pair<ConstantInt*, BasicBlock*>, 32> Table;
|
||||||
while (Lex.getKind() != lltok::rsquare) {
|
while (Lex.getKind() != lltok::rsquare) {
|
||||||
Value *Constant, *DestBB;
|
Value *Constant;
|
||||||
|
BasicBlock *DestBB;
|
||||||
|
|
||||||
if (ParseTypeAndValue(Constant, CondLoc, PFS) ||
|
if (ParseTypeAndValue(Constant, CondLoc, PFS) ||
|
||||||
ParseToken(lltok::comma, "expected ',' after case value") ||
|
ParseToken(lltok::comma, "expected ',' after case value") ||
|
||||||
ParseTypeAndValue(DestBB, BBLoc, PFS))
|
ParseTypeAndBasicBlock(DestBB, PFS))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!SeenCases.insert(Constant))
|
if (!SeenCases.insert(Constant))
|
||||||
return Error(CondLoc, "duplicate case value in switch");
|
return Error(CondLoc, "duplicate case value in switch");
|
||||||
if (!isa<ConstantInt>(Constant))
|
if (!isa<ConstantInt>(Constant))
|
||||||
return Error(CondLoc, "case value is not a constant integer");
|
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),
|
Table.push_back(std::make_pair(cast<ConstantInt>(Constant), DestBB));
|
||||||
cast<BasicBlock>(DestBB)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Lex.Lex(); // Eat the ']'.
|
Lex.Lex(); // Eat the ']'.
|
||||||
|
|
||||||
SwitchInst *SI = SwitchInst::Create(Cond, cast<BasicBlock>(DefaultBB),
|
SwitchInst *SI = SwitchInst::Create(Cond, DefaultBB, Table.size());
|
||||||
Table.size());
|
|
||||||
for (unsigned i = 0, e = Table.size(); i != e; ++i)
|
for (unsigned i = 0, e = Table.size(); i != e; ++i)
|
||||||
SI->addCase(Table[i].first, Table[i].second);
|
SI->addCase(Table[i].first, Table[i].second);
|
||||||
Inst = SI;
|
Inst = SI;
|
||||||
return false;
|
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
|
/// ParseInvoke
|
||||||
/// ::= 'invoke' OptionalCallingConv OptionalAttrs Type Value ParamList
|
/// ::= 'invoke' OptionalCallingConv OptionalAttrs Type Value ParamList
|
||||||
/// OptionalAttrs 'to' TypeAndValue 'unwind' TypeAndValue
|
/// OptionalAttrs 'to' TypeAndValue 'unwind' TypeAndValue
|
||||||
|
@ -3011,7 +3057,7 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) {
|
||||||
ValID CalleeID;
|
ValID CalleeID;
|
||||||
SmallVector<ParamInfo, 16> ArgList;
|
SmallVector<ParamInfo, 16> ArgList;
|
||||||
|
|
||||||
Value *NormalBB, *UnwindBB;
|
BasicBlock *NormalBB, *UnwindBB;
|
||||||
if (ParseOptionalCallingConv(CC) ||
|
if (ParseOptionalCallingConv(CC) ||
|
||||||
ParseOptionalAttrs(RetAttrs, 1) ||
|
ParseOptionalAttrs(RetAttrs, 1) ||
|
||||||
ParseType(RetType, RetTypeLoc, true /*void allowed*/) ||
|
ParseType(RetType, RetTypeLoc, true /*void allowed*/) ||
|
||||||
|
@ -3019,16 +3065,11 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) {
|
||||||
ParseParameterList(ArgList, PFS) ||
|
ParseParameterList(ArgList, PFS) ||
|
||||||
ParseOptionalAttrs(FnAttrs, 2) ||
|
ParseOptionalAttrs(FnAttrs, 2) ||
|
||||||
ParseToken(lltok::kw_to, "expected 'to' in invoke") ||
|
ParseToken(lltok::kw_to, "expected 'to' in invoke") ||
|
||||||
ParseTypeAndValue(NormalBB, PFS) ||
|
ParseTypeAndBasicBlock(NormalBB, PFS) ||
|
||||||
ParseToken(lltok::kw_unwind, "expected 'unwind' in invoke") ||
|
ParseToken(lltok::kw_unwind, "expected 'unwind' in invoke") ||
|
||||||
ParseTypeAndValue(UnwindBB, PFS))
|
ParseTypeAndBasicBlock(UnwindBB, PFS))
|
||||||
return true;
|
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
|
// 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
|
// 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.
|
// 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
|
// Finish off the Attributes and check them
|
||||||
AttrListPtr PAL = AttrListPtr::get(Attrs.begin(), Attrs.end());
|
AttrListPtr PAL = AttrListPtr::get(Attrs.begin(), Attrs.end());
|
||||||
|
|
||||||
InvokeInst *II = InvokeInst::Create(Callee, cast<BasicBlock>(NormalBB),
|
InvokeInst *II = InvokeInst::Create(Callee, NormalBB, UnwindBB,
|
||||||
cast<BasicBlock>(UnwindBB),
|
|
||||||
Args.begin(), Args.end());
|
Args.begin(), Args.end());
|
||||||
II->setCallingConv(CC);
|
II->setCallingConv(CC);
|
||||||
II->setAttributes(PAL);
|
II->setAttributes(PAL);
|
||||||
|
|
|
@ -230,6 +230,12 @@ namespace llvm {
|
||||||
Loc = Lex.getLoc();
|
Loc = Lex.getLoc();
|
||||||
return ParseTypeAndValue(V, PFS);
|
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 {
|
struct ParamInfo {
|
||||||
LocTy Loc;
|
LocTy Loc;
|
||||||
|
@ -264,6 +270,7 @@ namespace llvm {
|
||||||
bool ParseRet(Instruction *&Inst, BasicBlock *BB, PerFunctionState &PFS);
|
bool ParseRet(Instruction *&Inst, BasicBlock *BB, PerFunctionState &PFS);
|
||||||
bool ParseBr(Instruction *&Inst, PerFunctionState &PFS);
|
bool ParseBr(Instruction *&Inst, PerFunctionState &PFS);
|
||||||
bool ParseSwitch(Instruction *&Inst, PerFunctionState &PFS);
|
bool ParseSwitch(Instruction *&Inst, PerFunctionState &PFS);
|
||||||
|
bool ParseIndBr(Instruction *&Inst, PerFunctionState &PFS);
|
||||||
bool ParseInvoke(Instruction *&Inst, PerFunctionState &PFS);
|
bool ParseInvoke(Instruction *&Inst, PerFunctionState &PFS);
|
||||||
|
|
||||||
bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc,
|
bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc,
|
||||||
|
|
|
@ -111,7 +111,7 @@ namespace lltok {
|
||||||
kw_fptoui, kw_fptosi, kw_inttoptr, kw_ptrtoint, kw_bitcast,
|
kw_fptoui, kw_fptosi, kw_inttoptr, kw_ptrtoint, kw_bitcast,
|
||||||
kw_select, kw_va_arg,
|
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,
|
kw_malloc, kw_alloca, kw_free, kw_load, kw_store, kw_getelementptr,
|
||||||
|
|
||||||
|
|
|
@ -1951,7 +1951,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
|
||||||
}
|
}
|
||||||
break;
|
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)
|
if (Record.size() < 3 || (Record.size() & 1) == 0)
|
||||||
return Error("Invalid SWITCH record");
|
return Error("Invalid SWITCH record");
|
||||||
const Type *OpTy = getTypeByID(Record[0]);
|
const Type *OpTy = getTypeByID(Record[0]);
|
||||||
|
@ -1975,6 +1975,27 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
|
||||||
I = SI;
|
I = SI;
|
||||||
break;
|
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: {
|
case bitc::FUNC_CODE_INST_INVOKE: {
|
||||||
// INVOKE: [attrs, cc, normBB, unwindBB, fnty, op0,op1,op2, ...]
|
// INVOKE: [attrs, cc, normBB, unwindBB, fnty, op0,op1,op2, ...]
|
||||||
|
|
|
@ -1001,7 +1001,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
|
||||||
case Instruction::Br:
|
case Instruction::Br:
|
||||||
{
|
{
|
||||||
Code = bitc::FUNC_CODE_INST_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)));
|
Vals.push_back(VE.getValueID(II.getSuccessor(0)));
|
||||||
if (II.isConditional()) {
|
if (II.isConditional()) {
|
||||||
Vals.push_back(VE.getValueID(II.getSuccessor(1)));
|
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)
|
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
|
||||||
Vals.push_back(VE.getValueID(I.getOperand(i)));
|
Vals.push_back(VE.getValueID(I.getOperand(i)));
|
||||||
break;
|
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: {
|
case Instruction::Invoke: {
|
||||||
const InvokeInst *II = cast<InvokeInst>(&I);
|
const InvokeInst *II = cast<InvokeInst>(&I);
|
||||||
const Value *Callee(II->getCalledValue());
|
const Value *Callee(II->getCalledValue());
|
||||||
|
|
|
@ -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) {
|
void SelectionDAGLowering::visitFSub(User &I) {
|
||||||
// -0.0 - X --> fneg
|
// -0.0 - X --> fneg
|
||||||
|
|
|
@ -49,6 +49,7 @@ class GetElementPtrInst;
|
||||||
class GCFunctionInfo;
|
class GCFunctionInfo;
|
||||||
class ICmpInst;
|
class ICmpInst;
|
||||||
class IntToPtrInst;
|
class IntToPtrInst;
|
||||||
|
class IndBrInst;
|
||||||
class InvokeInst;
|
class InvokeInst;
|
||||||
class InsertElementInst;
|
class InsertElementInst;
|
||||||
class InsertValueInst;
|
class InsertValueInst;
|
||||||
|
@ -448,6 +449,7 @@ private:
|
||||||
void visitRet(ReturnInst &I);
|
void visitRet(ReturnInst &I);
|
||||||
void visitBr(BranchInst &I);
|
void visitBr(BranchInst &I);
|
||||||
void visitSwitch(SwitchInst &I);
|
void visitSwitch(SwitchInst &I);
|
||||||
|
void visitIndBr(IndBrInst &I);
|
||||||
void visitUnreachable(UnreachableInst &I) { /* noop */ }
|
void visitUnreachable(UnreachableInst &I) { /* noop */ }
|
||||||
|
|
||||||
// Helpers for visitSwitch
|
// Helpers for visitSwitch
|
||||||
|
|
|
@ -1832,7 +1832,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
|
||||||
writeOperand(BI.getSuccessor(1), true);
|
writeOperand(BI.getSuccessor(1), true);
|
||||||
|
|
||||||
} else if (isa<SwitchInst>(I)) {
|
} 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 << ' ';
|
Out << ' ';
|
||||||
writeOperand(Operand , true);
|
writeOperand(Operand , true);
|
||||||
Out << ", ";
|
Out << ", ";
|
||||||
|
@ -1846,6 +1846,19 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
|
||||||
writeOperand(I.getOperand(op+1), true);
|
writeOperand(I.getOperand(op+1), true);
|
||||||
}
|
}
|
||||||
Out << "\n ]";
|
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)) {
|
} else if (isa<PHINode>(I)) {
|
||||||
Out << ' ';
|
Out << ' ';
|
||||||
TypePrinter.print(I.getType(), Out);
|
TypePrinter.print(I.getType(), Out);
|
||||||
|
|
|
@ -103,6 +103,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
|
||||||
case Ret: return "ret";
|
case Ret: return "ret";
|
||||||
case Br: return "br";
|
case Br: return "br";
|
||||||
case Switch: return "switch";
|
case Switch: return "switch";
|
||||||
|
case IndBr: return "indbr";
|
||||||
case Invoke: return "invoke";
|
case Invoke: return "invoke";
|
||||||
case Unwind: return "unwind";
|
case Unwind: return "unwind";
|
||||||
case Unreachable: return "unreachable";
|
case Unreachable: return "unreachable";
|
||||||
|
|
|
@ -3086,6 +3086,118 @@ void SwitchInst::setSuccessorV(unsigned idx, BasicBlock *B) {
|
||||||
setSuccessor(idx, 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
|
// Define these methods here so vtables don't get emitted into every translation
|
||||||
// unit that uses these classes.
|
// unit that uses these classes.
|
||||||
|
|
||||||
|
@ -3410,6 +3522,15 @@ SwitchInst *SwitchInst::clone() const {
|
||||||
return New;
|
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 *InvokeInst::clone() const {
|
||||||
InvokeInst *New = new(getNumOperands()) InvokeInst(*this);
|
InvokeInst *New = new(getNumOperands()) InvokeInst(*this);
|
||||||
New->SubclassOptionalData = SubclassOptionalData;
|
New->SubclassOptionalData = SubclassOptionalData;
|
||||||
|
|
|
@ -24,3 +24,14 @@ Case4: ; preds = %0
|
||||||
ret i32 16
|
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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue