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
This commit is contained in:
Chris Lattner 2009-10-27 19:13:16 +00:00
parent 76b39e88e4
commit f9be95f867
17 changed files with 482 additions and 101 deletions

View File

@ -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>

View File

@ -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

View File

@ -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
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(53)
LAST_OTHER_INST(54)
#undef FIRST_TERM_INST
#undef HANDLE_TERM_INST

View File

@ -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
@ -2213,6 +2213,105 @@ struct OperandTraits<SwitchInst> : public HungoffOperandTraits<2> {
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
//===----------------------------------------------------------------------===//

View File

@ -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);}

View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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");

View File

@ -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());

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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";

View File

@ -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;

View File

@ -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
}