SIL: Add a switch_int instruction.

This will help represent cleanup blocks in the grown-up Clang way instead of the childish SILGen way, e.g.:

  retain %x
  retain %y
  ...
break_branch:
  %1 = int_literal 1 : $Builtin.Int64
  br cleanup(%1)
return_branch:
  %2 = int_literal 2 : $Builtin.Int64
  br cleanup(%2)
cleanup(%dest : $Builtin.Int64):
  release %z
  release %y
  switch %dest, case 1: break_dest, case 2: return_dest

Swift SVN r6753
This commit is contained in:
Joe Groff
2013-07-30 21:32:23 +00:00
parent 3e7eef56e7
commit 26c00fd429
7 changed files with 229 additions and 10 deletions

View File

@@ -551,6 +551,62 @@ OperandValueArrayRef CondBranchInst::getFalseArgs() const {
getFalseBB()->bbarg_size());
}
SwitchIntInst::SwitchIntInst(SILLocation Loc, SILValue Operand,
SILBasicBlock *DefaultBB,
ArrayRef<std::pair<APInt, SILBasicBlock*>> CaseBBs)
: TermInst(ValueKind::SwitchIntInst, Loc),
Operands(this, Operand),
NumCases(CaseBBs.size()),
HasDefault(bool(DefaultBB))
{
// Initialize the case and successor arrays.
auto *cases = getCaseBuf();
auto *succs = getSuccessorBuf();
unsigned words = getNumWordsForCase();
for (unsigned i = 0, size = CaseBBs.size(); i < size; ++i) {
assert(CaseBBs[i].first.getBitWidth() == getBitWidthForCase() &&
"switch_int case value is not same bit width as operand");
memcpy(cases + i*words, CaseBBs[i].first.getRawData(),
words * sizeof(llvm::integerPart));
::new (succs + i) SILSuccessor(this, CaseBBs[i].second);
}
if (HasDefault)
::new (succs + NumCases) SILSuccessor(this, DefaultBB);
}
SwitchIntInst::~SwitchIntInst() {
// Destroy the successor records to keep the CFG up to date.
auto *succs = getSuccessorBuf();
for (unsigned i = 0, end = NumCases + HasDefault; i < end; ++i) {
succs[i].~SILSuccessor();
}
}
SwitchIntInst *SwitchIntInst::create(SILLocation Loc, SILValue Operand,
SILBasicBlock *DefaultBB,
ArrayRef<std::pair<APInt, SILBasicBlock *>> CaseBBs,
SILFunction &F) {
// Allocate enough room for the instruction with tail-allocated data for all
// the APInt values and the SILSuccessor arrays. There are `CaseBBs.size()`
// APInts (each needing `getNumWords()` `llvm::integerPart`s of storage) and
// `CaseBBs.size() + (DefaultBB ? 1 : 0)` successors.
unsigned numCases = CaseBBs.size();
unsigned numSuccessors = numCases + (DefaultBB ? 1 : 0);
unsigned bits = Operand.getType().castTo<BuiltinIntegerType>()->getBitWidth();
unsigned words = (bits + llvm::integerPartWidth - 1) / llvm::integerPartWidth;
void *buf = F.getModule().allocate(sizeof(SwitchIntInst)
+ sizeof(llvm::integerPart) * numCases
* words
+ sizeof(SILSuccessor) * numSuccessors,
alignof(SwitchIntInst));
return ::new (buf) SwitchIntInst(Loc, Operand, DefaultBB, CaseBBs);
}
SwitchOneofInst::SwitchOneofInst(SILLocation Loc, SILValue Operand,
SILBasicBlock *DefaultBB,
ArrayRef<std::pair<OneOfElementDecl*, SILBasicBlock*>> CaseBBs)
@@ -584,8 +640,8 @@ SwitchOneofInst *SwitchOneofInst::create(SILLocation Loc, SILValue Operand,
ArrayRef<std::pair<OneOfElementDecl*, SILBasicBlock*>> CaseBBs,
SILFunction &F) {
// Allocate enough room for the instruction with tail-allocated
// OneOfElementDecl and SILSuccessor arrays. There are CaseBBs.size() decls
// CaseBBs.size() + (DefaultBB ? 1 : 0) successors.
// OneOfElementDecl and SILSuccessor arrays. There are `CaseBBs.size()` decls
// and `CaseBBs.size() + (DefaultBB ? 1 : 0)` successors.
unsigned numCases = CaseBBs.size();
unsigned numSuccessors = numCases + (DefaultBB ? 1 : 0);