Commit d1a971a1 by Karl Schimpf

Add switch instruction to Subzero bitcode reader.

parent cc0ee13f
...@@ -228,6 +228,13 @@ Type getCompareResultType(Type Ty) { ...@@ -228,6 +228,13 @@ Type getCompareResultType(Type Ty) {
return IceType_void; return IceType_void;
} }
SizeT getScalarIntBitWidth(Type Ty) {
assert(isScalarIntegerType(Ty));
if (Ty == Ice::IceType_i1)
return 1;
return typeWidthInBytes(Ty) * CHAR_BIT;
}
// ======================== Dump routines ======================== // // ======================== Dump routines ======================== //
const char *typeString(Type Ty) { const char *typeString(Type Ty) {
......
...@@ -66,6 +66,9 @@ bool isLoadStoreType(Type Ty); ...@@ -66,6 +66,9 @@ bool isLoadStoreType(Type Ty);
/// allowed. /// allowed.
Type getCompareResultType(Type Ty); Type getCompareResultType(Type Ty);
/// Returns the number of bits in a scalar integer type.
SizeT getScalarIntBitWidth(Type Ty);
template <typename StreamType> template <typename StreamType>
inline StreamType &operator<<(StreamType &Str, const Type &Ty) { inline StreamType &operator<<(StreamType &Str, const Type &Ty) {
Str << typeString(Ty); Str << typeString(Ty);
......
...@@ -1007,7 +1007,7 @@ private: ...@@ -1007,7 +1007,7 @@ private:
// Must be forward reference, expand vector to accommodate. // Must be forward reference, expand vector to accommodate.
if (LocalIndex >= LocalOperands.size()) if (LocalIndex >= LocalOperands.size())
LocalOperands.resize(LocalIndex+1); LocalOperands.resize(LocalIndex + 1);
// If element not defined, set it. // If element not defined, set it.
Ice::Operand *OldOp = LocalOperands[LocalIndex]; Ice::Operand *OldOp = LocalOperands[LocalIndex];
...@@ -1023,8 +1023,8 @@ private: ...@@ -1023,8 +1023,8 @@ private:
// Error has occurred. // Error has occurred.
std::string Buffer; std::string Buffer;
raw_string_ostream StrBuf(Buffer); raw_string_ostream StrBuf(Buffer);
StrBuf << "Multiple definitions for index " << Index StrBuf << "Multiple definitions for index " << Index << ": " << *Op
<< ": " << *Op << " and " << *OldOp; << " and " << *OldOp;
Error(StrBuf.str()); Error(StrBuf.str());
// TODO(kschimpf) Remove error recovery once implementation complete. // TODO(kschimpf) Remove error recovery once implementation complete.
LocalOperands[LocalIndex] = Op; LocalOperands[LocalIndex] = Op;
...@@ -1037,9 +1037,7 @@ private: ...@@ -1037,9 +1037,7 @@ private:
} }
// Returns the absolute index of the next value generating instruction. // Returns the absolute index of the next value generating instruction.
uint32_t getNextInstIndex() const { uint32_t getNextInstIndex() const { return NextLocalInstIndex; }
return NextLocalInstIndex;
}
// Generates type error message for binary operator Op // Generates type error message for binary operator Op
// operating on Type OpTy. // operating on Type OpTy.
...@@ -1682,6 +1680,65 @@ void FunctionParser::ProcessRecord() { ...@@ -1682,6 +1680,65 @@ void FunctionParser::ProcessRecord() {
InstIsTerminating = true; InstIsTerminating = true;
break; break;
} }
case naclbitc::FUNC_CODE_INST_SWITCH: {
// SWITCH: [Condty, Cond, BbIndex, NumCases Case ...]
// where Case = [1, 1, Value, BbIndex].
//
// Note: Unlike most instructions, we don't infer the type of
// Cond, but provide it as a separate field. There are also
// unnecesary data fields (i.e. constants 1). These were not
// cleaned up in PNaCl bitcode because the bitcode format was
// already frozen when the problem was noticed.
if (!isValidRecordSizeAtLeast(4, "function block switch"))
return;
Ice::Type CondTy =
Context->convertToIceType(Context->getTypeByID(Values[0]));
if (!Ice::isScalarIntegerType(CondTy)) {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Case condition must be non-wide integer. Found: " << CondTy;
Error(StrBuf.str());
return;
}
Ice::SizeT BitWidth = Ice::getScalarIntBitWidth(CondTy);
Ice::Operand *Cond = getRelativeOperand(Values[1], BaseIndex);
if (CondTy != Cond->getType()) {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Case condition expects type " << CondTy
<< ". Found: " << Cond->getType();
Error(StrBuf.str());
return;
}
Ice::CfgNode *DefaultLabel = getBranchBasicBlock(Values[2]);
unsigned NumCases = Values[3];
// Now recognize each of the cases.
if (!isValidRecordSize(4 + NumCases * 4, "Function block switch"))
return;
Ice::InstSwitch *Switch =
Ice::InstSwitch::create(Func, NumCases, Cond, DefaultLabel);
unsigned ValCaseIndex = 4; // index to beginning of case entry.
for (unsigned CaseIndex = 0; CaseIndex < NumCases;
++CaseIndex, ValCaseIndex += 4) {
if (Values[ValCaseIndex] != 1 || Values[ValCaseIndex+1] != 1) {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Sequence [1, 1, value, label] expected for case entry "
<< "in switch record. (at index" << ValCaseIndex << ")";
Error(StrBuf.str());
return;
}
APInt Value(BitWidth,
NaClDecodeSignRotatedValue(Values[ValCaseIndex + 2]),
true);
Ice::CfgNode *Label = getBranchBasicBlock(Values[ValCaseIndex + 3]);
Switch->addBranch(CaseIndex, Value.getSExtValue(), Label);
}
CurrentNode->appendInst(Switch);
InstIsTerminating = true;
break;
}
case naclbitc::FUNC_CODE_INST_UNREACHABLE: { case naclbitc::FUNC_CODE_INST_UNREACHABLE: {
// UNREACHABLE: [] // UNREACHABLE: []
if (!isValidRecordSize(0, "function block unreachable")) if (!isValidRecordSize(0, "function block unreachable"))
...@@ -1781,11 +1838,10 @@ void FunctionParser::ProcessRecord() { ...@@ -1781,11 +1838,10 @@ void FunctionParser::ProcessRecord() {
// FORWARDTYPEREF: [opval, ty] // FORWARDTYPEREF: [opval, ty]
if (!isValidRecordSize(2, "function block forward type ref")) if (!isValidRecordSize(2, "function block forward type ref"))
return; return;
setOperand(Values[0], createInstVar( setOperand(Values[0], createInstVar(Context->convertToIceType(
Context->convertToIceType(Context->getTypeByID(Values[1])))); Context->getTypeByID(Values[1]))));
break; break;
} }
case naclbitc::FUNC_CODE_INST_SWITCH:
case naclbitc::FUNC_CODE_INST_CALL: case naclbitc::FUNC_CODE_INST_CALL:
case naclbitc::FUNC_CODE_INST_CALL_INDIRECT: case naclbitc::FUNC_CODE_INST_CALL_INDIRECT:
default: default:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment