diff --git a/docs/LangRef.html b/docs/LangRef.html index 73ee31b3245..c12bacff59b 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -110,6 +110,7 @@
  • 'ret' Instruction
  • 'br' Instruction
  • 'switch' Instruction
  • +
  • 'indbr' Instruction
  • 'invoke' Instruction
  • 'unwind' Instruction
  • 'unreachable' Instruction
  • @@ -2511,6 +2512,7 @@ Instructions 'ret' instruction, the 'br' instruction, the 'switch' instruction, the + ''indbr' Instruction, the 'invoke' instruction, the 'unwind' instruction, and the 'unreachable' instruction.

    @@ -2669,6 +2671,54 @@ IfUnequal: + + +
    + 'indbr' Instruction +
    + +
    + +
    Syntax:
    +
    +  indbr <somety>* <address>, [ label <dest1>, label <dest2>, ... ]
    +
    + +
    Overview:
    + +

    The 'indbr' instruction implements an indirect branch to a label + within the current function, whose address is specified by + "address".

    + +
    Arguments:
    + +

    The 'address' 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.

    + +

    This destination list is required so that dataflow analysis has an accurate + understanding of the CFG.

    + +
    Semantics:
    + +

    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.

    + +
    Implementation:
    + +

    This is typically implemented with a jump through a register.

    + +
    Example:
    +
    + switch i8* %Addr, [ label %bb1, label %bb2, label %bb3 ]
    +
    + +
    + +
    'invoke' Instruction diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index dccd8e035d7..55bd2566bad 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -209,7 +209,7 @@ namespace bitc { FUNC_CODE_INST_RET = 10, // RET: [opty,opval] FUNC_CODE_INST_BR = 11, // BR: [bb#, bb#, cond] or [bb#] - FUNC_CODE_INST_SWITCH = 12, // SWITCH: [opty, opval, n, n x ops] + FUNC_CODE_INST_SWITCH = 12, // SWITCH: [opty, operands...] FUNC_CODE_INST_INVOKE = 13, // INVOKE: [attr, fnty, op0,op1, ...] FUNC_CODE_INST_UNWIND = 14, // UNWIND FUNC_CODE_INST_UNREACHABLE = 15, // UNREACHABLE @@ -236,7 +236,8 @@ namespace bitc { FUNC_CODE_INST_CMP2 = 28, // CMP2: [opty, opval, opval, pred] // new select on i1 or [N x i1] FUNC_CODE_INST_VSELECT = 29, // VSELECT: [ty,opval,opval,predty,pred] - FUNC_CODE_INST_INBOUNDS_GEP = 30 // INBOUNDS_GEP: [n x operands] + FUNC_CODE_INST_INBOUNDS_GEP= 30, // INBOUNDS_GEP: [n x operands] + FUNC_CODE_INST_INDBR = 31 // INDBR: [opty, operands...] }; } // End bitc namespace } // End llvm namespace diff --git a/include/llvm/Instruction.def b/include/llvm/Instruction.def index ec86b35364e..c0adf40316b 100644 --- a/include/llvm/Instruction.def +++ b/include/llvm/Instruction.def @@ -97,78 +97,79 @@ HANDLE_TERM_INST ( 1, Ret , ReturnInst) HANDLE_TERM_INST ( 2, Br , BranchInst) HANDLE_TERM_INST ( 3, Switch , SwitchInst) -HANDLE_TERM_INST ( 4, Invoke , InvokeInst) -HANDLE_TERM_INST ( 5, Unwind , UnwindInst) -HANDLE_TERM_INST ( 6, Unreachable, UnreachableInst) - LAST_TERM_INST ( 6) +HANDLE_TERM_INST ( 4, IndBr , IndBrInst) +HANDLE_TERM_INST ( 5, Invoke , InvokeInst) +HANDLE_TERM_INST ( 6, Unwind , UnwindInst) +HANDLE_TERM_INST ( 7, Unreachable, UnreachableInst) + LAST_TERM_INST ( 7) // Standard binary operators... - FIRST_BINARY_INST( 7) -HANDLE_BINARY_INST( 7, Add , BinaryOperator) -HANDLE_BINARY_INST( 8, FAdd , BinaryOperator) -HANDLE_BINARY_INST( 9, Sub , BinaryOperator) -HANDLE_BINARY_INST(10, FSub , BinaryOperator) -HANDLE_BINARY_INST(11, Mul , BinaryOperator) -HANDLE_BINARY_INST(12, FMul , BinaryOperator) -HANDLE_BINARY_INST(13, UDiv , BinaryOperator) -HANDLE_BINARY_INST(14, SDiv , BinaryOperator) -HANDLE_BINARY_INST(15, FDiv , BinaryOperator) -HANDLE_BINARY_INST(16, URem , BinaryOperator) -HANDLE_BINARY_INST(17, SRem , BinaryOperator) -HANDLE_BINARY_INST(18, FRem , BinaryOperator) + FIRST_BINARY_INST( 8) +HANDLE_BINARY_INST( 8, Add , BinaryOperator) +HANDLE_BINARY_INST( 9, FAdd , BinaryOperator) +HANDLE_BINARY_INST(10, Sub , BinaryOperator) +HANDLE_BINARY_INST(11, FSub , BinaryOperator) +HANDLE_BINARY_INST(12, Mul , BinaryOperator) +HANDLE_BINARY_INST(13, FMul , BinaryOperator) +HANDLE_BINARY_INST(14, UDiv , BinaryOperator) +HANDLE_BINARY_INST(15, SDiv , BinaryOperator) +HANDLE_BINARY_INST(16, FDiv , BinaryOperator) +HANDLE_BINARY_INST(17, URem , BinaryOperator) +HANDLE_BINARY_INST(18, SRem , BinaryOperator) +HANDLE_BINARY_INST(19, FRem , BinaryOperator) // Logical operators (integer operands) -HANDLE_BINARY_INST(19, Shl , BinaryOperator) // Shift left (logical) -HANDLE_BINARY_INST(20, LShr , BinaryOperator) // Shift right (logical) -HANDLE_BINARY_INST(21, AShr , BinaryOperator) // Shift right (arithmetic) -HANDLE_BINARY_INST(22, And , BinaryOperator) -HANDLE_BINARY_INST(23, Or , BinaryOperator) -HANDLE_BINARY_INST(24, Xor , BinaryOperator) - LAST_BINARY_INST(24) +HANDLE_BINARY_INST(20, Shl , BinaryOperator) // Shift left (logical) +HANDLE_BINARY_INST(21, LShr , BinaryOperator) // Shift right (logical) +HANDLE_BINARY_INST(22, AShr , BinaryOperator) // Shift right (arithmetic) +HANDLE_BINARY_INST(23, And , BinaryOperator) +HANDLE_BINARY_INST(24, Or , BinaryOperator) +HANDLE_BINARY_INST(25, Xor , BinaryOperator) + LAST_BINARY_INST(25) // Memory operators... - FIRST_MEMORY_INST(25) -HANDLE_MEMORY_INST(25, Alloca, AllocaInst) // Stack management -HANDLE_MEMORY_INST(26, Load , LoadInst ) // Memory manipulation instrs -HANDLE_MEMORY_INST(27, Store , StoreInst ) -HANDLE_MEMORY_INST(28, GetElementPtr, GetElementPtrInst) - LAST_MEMORY_INST(28) + FIRST_MEMORY_INST(26) +HANDLE_MEMORY_INST(26, Alloca, AllocaInst) // Stack management +HANDLE_MEMORY_INST(27, Load , LoadInst ) // Memory manipulation instrs +HANDLE_MEMORY_INST(28, Store , StoreInst ) +HANDLE_MEMORY_INST(29, GetElementPtr, GetElementPtrInst) + LAST_MEMORY_INST(29) // Cast operators ... // NOTE: The order matters here because CastInst::isEliminableCastPair // NOTE: (see Instructions.cpp) encodes a table based on this ordering. - FIRST_CAST_INST(29) -HANDLE_CAST_INST(29, Trunc , TruncInst ) // Truncate integers -HANDLE_CAST_INST(30, ZExt , ZExtInst ) // Zero extend integers -HANDLE_CAST_INST(31, SExt , SExtInst ) // Sign extend integers -HANDLE_CAST_INST(32, FPToUI , FPToUIInst ) // floating point -> UInt -HANDLE_CAST_INST(33, FPToSI , FPToSIInst ) // floating point -> SInt -HANDLE_CAST_INST(34, UIToFP , UIToFPInst ) // UInt -> floating point -HANDLE_CAST_INST(35, SIToFP , SIToFPInst ) // SInt -> floating point -HANDLE_CAST_INST(36, FPTrunc , FPTruncInst ) // Truncate floating point -HANDLE_CAST_INST(37, FPExt , FPExtInst ) // Extend floating point -HANDLE_CAST_INST(38, PtrToInt, PtrToIntInst) // Pointer -> Integer -HANDLE_CAST_INST(39, IntToPtr, IntToPtrInst) // Integer -> Pointer -HANDLE_CAST_INST(40, BitCast , BitCastInst ) // Type cast - LAST_CAST_INST(40) + FIRST_CAST_INST(30) +HANDLE_CAST_INST(30, Trunc , TruncInst ) // Truncate integers +HANDLE_CAST_INST(31, ZExt , ZExtInst ) // Zero extend integers +HANDLE_CAST_INST(32, SExt , SExtInst ) // Sign extend integers +HANDLE_CAST_INST(33, FPToUI , FPToUIInst ) // floating point -> UInt +HANDLE_CAST_INST(34, FPToSI , FPToSIInst ) // floating point -> SInt +HANDLE_CAST_INST(35, UIToFP , UIToFPInst ) // UInt -> floating point +HANDLE_CAST_INST(36, SIToFP , SIToFPInst ) // SInt -> floating point +HANDLE_CAST_INST(37, FPTrunc , FPTruncInst ) // Truncate floating point +HANDLE_CAST_INST(38, FPExt , FPExtInst ) // Extend floating point +HANDLE_CAST_INST(39, PtrToInt, PtrToIntInst) // Pointer -> Integer +HANDLE_CAST_INST(40, IntToPtr, IntToPtrInst) // Integer -> Pointer +HANDLE_CAST_INST(41, BitCast , BitCastInst ) // Type cast + LAST_CAST_INST(41) // Other operators... - FIRST_OTHER_INST(41) -HANDLE_OTHER_INST(41, ICmp , ICmpInst ) // Integer comparison instruction -HANDLE_OTHER_INST(42, FCmp , FCmpInst ) // Floating point comparison instr. -HANDLE_OTHER_INST(43, PHI , PHINode ) // PHI node instruction -HANDLE_OTHER_INST(44, Call , CallInst ) // Call a function -HANDLE_OTHER_INST(45, Select , SelectInst ) // select instruction -HANDLE_OTHER_INST(46, UserOp1, Instruction) // May be used internally in a pass -HANDLE_OTHER_INST(47, UserOp2, Instruction) // Internal to passes only -HANDLE_OTHER_INST(48, VAArg , VAArgInst ) // vaarg instruction -HANDLE_OTHER_INST(49, ExtractElement, ExtractElementInst)// extract from vector -HANDLE_OTHER_INST(50, InsertElement, InsertElementInst) // insert into vector -HANDLE_OTHER_INST(51, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. -HANDLE_OTHER_INST(52, ExtractValue, ExtractValueInst)// extract from aggregate -HANDLE_OTHER_INST(53, InsertValue, InsertValueInst) // insert into aggregate + 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 diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index 2f69171bc81..9a9d718b00f 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -2076,7 +2076,7 @@ class SwitchInst : public TerminatorInst { // Operand[1] = Default basic block destination // Operand[2n ] = Value to match // Operand[2n+1] = BasicBlock to go to on match - SwitchInst(const SwitchInst &RI); + SwitchInst(const SwitchInst &SI); void init(Value *Value, BasicBlock *Default, unsigned NumCases); void resizeOperands(unsigned No); // allocate space for exactly zero operands @@ -2088,7 +2088,7 @@ class SwitchInst : public TerminatorInst { /// be specified here to make memory allocation more efficient. This /// constructor can also autoinsert before another instruction. SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, - Instruction *InsertBefore = 0); + Instruction *InsertBefore); /// SwitchInst ctor - Create a new switch instruction, specifying a value to /// switch on and a default destination. The number of additional cases can @@ -2213,6 +2213,105 @@ struct OperandTraits : 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(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(V) && classof(cast(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits : public HungoffOperandTraits<1> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndBrInst, Value) + + //===----------------------------------------------------------------------===// // InvokeInst Class //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/InstVisitor.h b/include/llvm/Support/InstVisitor.h index ae35a3c281a..ce9788483a5 100644 --- a/include/llvm/Support/InstVisitor.h +++ b/include/llvm/Support/InstVisitor.h @@ -160,6 +160,7 @@ public: RetTy visitReturnInst(ReturnInst &I) { DELEGATE(TerminatorInst);} RetTy visitBranchInst(BranchInst &I) { DELEGATE(TerminatorInst);} RetTy visitSwitchInst(SwitchInst &I) { DELEGATE(TerminatorInst);} + RetTy visitIndBrInst(IndBrInst &I) { DELEGATE(TerminatorInst);} RetTy visitInvokeInst(InvokeInst &I) { DELEGATE(TerminatorInst);} RetTy visitUnwindInst(UnwindInst &I) { DELEGATE(TerminatorInst);} RetTy visitUnreachableInst(UnreachableInst &I) { DELEGATE(TerminatorInst);} diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index 4fb7ea9e29f..1003907974d 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -645,6 +645,7 @@ lltok::Kind LLLexer::LexIdentifier() { INSTKEYWORD(ret, Ret); INSTKEYWORD(br, Br); INSTKEYWORD(switch, Switch); + INSTKEYWORD(indbr, IndBr); INSTKEYWORD(invoke, Invoke); INSTKEYWORD(unwind, Unwind); INSTKEYWORD(unreachable, Unreachable); diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index fa803bb1e9f..cf16e42b6a8 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -2412,6 +2412,18 @@ bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState &PFS) { ParseValue(T, V, PFS); } +bool LLParser::ParseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc, + PerFunctionState &PFS) { + Value *V; + Loc = Lex.getLoc(); + if (ParseTypeAndValue(V, PFS)) return true; + if (!isa(V)) + return Error(Loc, "expected a basic block"); + BB = cast(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(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(Op1)) - return Error(Loc, "true destination of branch must be a basic block"); - if (!isa(Op2)) - return Error(Loc2, "true destination of branch must be a basic block"); - - Inst = BranchInst::Create(cast(Op1), cast(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(Cond->getType())) return Error(CondLoc, "switch condition must have integer type"); - if (!isa(DefaultBB)) - return Error(BBLoc, "default destination must be a basic block"); // Parse the jump table pairs. SmallPtrSet SeenCases; SmallVector, 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(Constant)) return Error(CondLoc, "case value is not a constant integer"); - if (!isa(DestBB)) - return Error(BBLoc, "case destination is not a basic block"); - Table.push_back(std::make_pair(cast(Constant), - cast(DestBB))); + Table.push_back(std::make_pair(cast(Constant), DestBB)); } Lex.Lex(); // Eat the ']'. - SwitchInst *SI = SwitchInst::Create(Cond, cast(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(Address->getType())) + return Error(AddrLoc, "indbr address must have pointer type"); + + // Parse the destination list. + SmallVector 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 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(NormalBB)) - return Error(CallLoc, "normal destination is not a basic block"); - if (!isa(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(NormalBB), - cast(UnwindBB), + InvokeInst *II = InvokeInst::Create(Callee, NormalBB, UnwindBB, Args.begin(), Args.end()); II->setCallingConv(CC); II->setAttributes(PAL); diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index b6877bc7c11..37473a0a19b 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -230,7 +230,13 @@ namespace llvm { Loc = Lex.getLoc(); return ParseTypeAndValue(V, PFS); } - + bool ParseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc, + PerFunctionState &PFS); + bool ParseTypeAndBasicBlock(BasicBlock *&BB, PerFunctionState &PFS) { + LocTy Loc; + return ParseTypeAndBasicBlock(BB, Loc, PFS); + } + struct ParamInfo { LocTy Loc; Value *V; @@ -264,6 +270,7 @@ namespace llvm { bool ParseRet(Instruction *&Inst, BasicBlock *BB, PerFunctionState &PFS); bool ParseBr(Instruction *&Inst, PerFunctionState &PFS); bool ParseSwitch(Instruction *&Inst, PerFunctionState &PFS); + bool ParseIndBr(Instruction *&Inst, PerFunctionState &PFS); bool ParseInvoke(Instruction *&Inst, PerFunctionState &PFS); bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc, diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index f5072fe52f9..a25b6f08c0d 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -111,7 +111,7 @@ namespace lltok { kw_fptoui, kw_fptosi, kw_inttoptr, kw_ptrtoint, kw_bitcast, kw_select, kw_va_arg, - kw_ret, kw_br, kw_switch, kw_invoke, kw_unwind, kw_unreachable, + kw_ret, kw_br, kw_switch, kw_indbr, kw_invoke, kw_unwind, kw_unreachable, kw_malloc, kw_alloca, kw_free, kw_load, kw_store, kw_getelementptr, diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index b392122b778..41803c0eb45 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1951,7 +1951,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { } break; } - case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, opval, n, n x ops] + case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...] if (Record.size() < 3 || (Record.size() & 1) == 0) return Error("Invalid SWITCH record"); const Type *OpTy = getTypeByID(Record[0]); @@ -1975,7 +1975,28 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { I = SI; break; } - + case bitc::FUNC_CODE_INST_INDBR: { // INDBR: [opty, op0, op1, ...] + if (Record.size() < 2) + return Error("Invalid INDBR record"); + const Type *OpTy = getTypeByID(Record[0]); + Value *Address = getFnValueByID(Record[1], OpTy); + if (OpTy == 0 || Address == 0) + return Error("Invalid INDBR record"); + unsigned NumDests = Record.size()-2; + IndBrInst *IBI = IndBrInst::Create(Address, NumDests); + InstructionList.push_back(IBI); + for (unsigned i = 0, e = NumDests; i != e; ++i) { + if (BasicBlock *DestBB = getBasicBlock(Record[2+i])) { + IBI->addDestination(DestBB); + } else { + delete IBI; + return Error("Invalid INDBR record!"); + } + } + I = IBI; + break; + } + case bitc::FUNC_CODE_INST_INVOKE: { // INVOKE: [attrs, cc, normBB, unwindBB, fnty, op0,op1,op2, ...] if (Record.size() < 4) return Error("Invalid INVOKE record"); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index aee825ce52b..c0f97c19687 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1001,7 +1001,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, case Instruction::Br: { Code = bitc::FUNC_CODE_INST_BR; - BranchInst &II(cast(I)); + BranchInst &II = cast(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(&I); const Value *Callee(II->getCalledValue()); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index b220d55f548..73c9c5f57ec 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -2131,6 +2131,11 @@ void SelectionDAGLowering::visitSwitch(SwitchInst &SI) { } } +void SelectionDAGLowering::visitIndBr(IndBrInst &I) { + fprintf(stderr, "indbr codegen not implemented yet"); + abort(); +} + void SelectionDAGLowering::visitFSub(User &I) { // -0.0 - X --> fneg diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h index 74705514de6..9aca707ecfc 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.h @@ -49,6 +49,7 @@ class GetElementPtrInst; class GCFunctionInfo; class ICmpInst; class IntToPtrInst; +class IndBrInst; class InvokeInst; class InsertElementInst; class InsertValueInst; @@ -448,6 +449,7 @@ private: void visitRet(ReturnInst &I); void visitBr(BranchInst &I); void visitSwitch(SwitchInst &I); + void visitIndBr(IndBrInst &I); void visitUnreachable(UnreachableInst &I) { /* noop */ } // Helpers for visitSwitch diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 59ee3757a33..5a92432062e 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -1832,7 +1832,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) { writeOperand(BI.getSuccessor(1), true); } else if (isa(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(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(I)) { Out << ' '; TypePrinter.print(I.getType(), Out); diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp index def7b3b4ac7..4e8922230d6 100644 --- a/lib/VMCore/Instruction.cpp +++ b/lib/VMCore/Instruction.cpp @@ -103,6 +103,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) { case Ret: return "ret"; case Br: return "br"; case Switch: return "switch"; + case IndBr: return "indbr"; case Invoke: return "invoke"; case Unwind: return "unwind"; case Unreachable: return "unreachable"; diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 02d5af0120e..61b8044ead3 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -3086,6 +3086,118 @@ void SwitchInst::setSuccessorV(unsigned idx, BasicBlock *B) { setSuccessor(idx, B); } +//===----------------------------------------------------------------------===// +// SwitchInst Implementation +//===----------------------------------------------------------------------===// + +void IndBrInst::init(Value *Address, unsigned NumDests) { + assert(Address); + ReservedSpace = 1+NumDests; + NumOperands = 1; + OperandList = allocHungoffUses(ReservedSpace); + + OperandList[0] = Address; +} + + +/// resizeOperands - resize operands - This adjusts the length of the operands +/// list according to the following behavior: +/// 1. If NumOps == 0, grow the operand list in response to a push_back style +/// of operation. This grows the number of ops by 2 times. +/// 2. If NumOps > NumOperands, reserve space for NumOps operands. +/// 3. If NumOps == NumOperands, trim the reserved space. +/// +void IndBrInst::resizeOperands(unsigned NumOps) { + unsigned e = getNumOperands(); + if (NumOps == 0) { + NumOps = e*2; + } else if (NumOps*2 > NumOperands) { + // No resize needed. + if (ReservedSpace >= NumOps) return; + } else if (NumOps == NumOperands) { + if (ReservedSpace == NumOps) return; + } else { + return; + } + + ReservedSpace = NumOps; + Use *NewOps = allocHungoffUses(NumOps); + Use *OldOps = OperandList; + for (unsigned i = 0; i != e; ++i) + NewOps[i] = OldOps[i]; + OperandList = NewOps; + if (OldOps) Use::zap(OldOps, OldOps + e, true); +} + +IndBrInst::IndBrInst(Value *Address, unsigned NumCases, + Instruction *InsertBefore) +: TerminatorInst(Type::getVoidTy(Address->getContext()), Instruction::IndBr, + 0, 0, InsertBefore) { + init(Address, NumCases); +} + +IndBrInst::IndBrInst(Value *Address, unsigned NumCases, BasicBlock *InsertAtEnd) +: TerminatorInst(Type::getVoidTy(Address->getContext()), Instruction::IndBr, + 0, 0, InsertAtEnd) { + init(Address, NumCases); +} + +IndBrInst::IndBrInst(const IndBrInst &IBI) + : TerminatorInst(Type::getVoidTy(IBI.getContext()), Instruction::IndBr, + allocHungoffUses(IBI.getNumOperands()), + IBI.getNumOperands()) { + Use *OL = OperandList, *InOL = IBI.OperandList; + for (unsigned i = 0, E = IBI.getNumOperands(); i != E; ++i) + OL[i] = InOL[i]; + SubclassOptionalData = IBI.SubclassOptionalData; +} + +IndBrInst::~IndBrInst() { + dropHungoffUses(OperandList); +} + +/// addDestination - Add a destination. +/// +void IndBrInst::addDestination(BasicBlock *DestBB) { + unsigned OpNo = NumOperands; + if (OpNo+1 > ReservedSpace) + resizeOperands(0); // Get more space! + // Initialize some new operands. + assert(OpNo < ReservedSpace && "Growing didn't work!"); + NumOperands = OpNo+1; + OperandList[OpNo] = DestBB; +} + +/// removeDestination - This method removes the specified successor from the +/// indbr instruction. +void IndBrInst::removeDestination(unsigned idx) { + assert(idx < getNumOperands()-1 && "Successor index out of range!"); + + unsigned NumOps = getNumOperands(); + Use *OL = OperandList; + + // Replace this value with the last one. + OL[idx+1] = OL[NumOps-1]; + + // Nuke the last value. + OL[NumOps-1].set(0); + NumOperands = NumOps-1; +} + +BasicBlock *IndBrInst::getSuccessorV(unsigned idx) const { + return getSuccessor(idx); +} +unsigned IndBrInst::getNumSuccessorsV() const { + return getNumSuccessors(); +} +void IndBrInst::setSuccessorV(unsigned idx, BasicBlock *B) { + setSuccessor(idx, B); +} + +//===----------------------------------------------------------------------===// +// clone() implementations +//===----------------------------------------------------------------------===// + // Define these methods here so vtables don't get emitted into every translation // unit that uses these classes. @@ -3410,6 +3522,15 @@ SwitchInst *SwitchInst::clone() const { return New; } +IndBrInst *IndBrInst::clone() const { + IndBrInst *New = new IndBrInst(*this); + New->SubclassOptionalData = SubclassOptionalData; + if (hasMetadata()) + getContext().pImpl->TheMetadata.ValueIsCloned(this, New); + return New; +} + + InvokeInst *InvokeInst::clone() const { InvokeInst *New = new(getNumOperands()) InvokeInst(*this); New->SubclassOptionalData = SubclassOptionalData; diff --git a/test/Feature/terminators.ll b/test/Feature/terminators.ll index 417f56b58d0..d1b97108d2b 100644 --- a/test/Feature/terminators.ll +++ b/test/Feature/terminators.ll @@ -24,3 +24,14 @@ Case4: ; preds = %0 ret i32 16 } + + +define i32 @indbrtest(i8* %P, i32* %Q) { + indbr i8* %P, [label %BB1, label %BB2, label %BB3] +BB1: + indbr i32* %Q, [] +BB2: + indbr i32* %Q, [label %BB1, label %BB2] +BB3: + ret i32 2 +}