 Chromium Code Reviews
 Chromium Code Reviews Issue 576243002:
  Add switch instruction to Subzero bitcode reader.  (Closed) 
  Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
    
  
    Issue 576243002:
  Add switch instruction to Subzero bitcode reader.  (Closed) 
  Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master| Index: src/PNaClTranslator.cpp | 
| diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp | 
| index d63232f2be9ff5a29f5326cddd71becf019fc7c6..afc35be7617e2d948be480975a08ec377d6ab3df 100644 | 
| --- a/src/PNaClTranslator.cpp | 
| +++ b/src/PNaClTranslator.cpp | 
| @@ -1007,7 +1007,7 @@ private: | 
| // Must be forward reference, expand vector to accommodate. | 
| if (LocalIndex >= LocalOperands.size()) | 
| - LocalOperands.resize(LocalIndex+1); | 
| + LocalOperands.resize(LocalIndex + 1); | 
| // If element not defined, set it. | 
| Ice::Operand *OldOp = LocalOperands[LocalIndex]; | 
| @@ -1023,8 +1023,8 @@ private: | 
| // Error has occurred. | 
| std::string Buffer; | 
| raw_string_ostream StrBuf(Buffer); | 
| - StrBuf << "Multiple definitions for index " << Index | 
| - << ": " << *Op << " and " << *OldOp; | 
| + StrBuf << "Multiple definitions for index " << Index << ": " << *Op | 
| + << " and " << *OldOp; | 
| Error(StrBuf.str()); | 
| // TODO(kschimpf) Remove error recovery once implementation complete. | 
| LocalOperands[LocalIndex] = Op; | 
| @@ -1037,9 +1037,7 @@ private: | 
| } | 
| // Returns the absolute index of the next value generating instruction. | 
| - uint32_t getNextInstIndex() const { | 
| - return NextLocalInstIndex; | 
| - } | 
| + uint32_t getNextInstIndex() const { return NextLocalInstIndex; } | 
| // Generates type error message for binary operator Op | 
| // operating on Type OpTy. | 
| @@ -1682,6 +1680,70 @@ void FunctionParser::ProcessRecord() { | 
| InstIsTerminating = true; | 
| 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])); | 
| 
Jim Stichnoth
2014/09/17 20:18:20
Consider defining "unsigned ValIndex = 0;" up here
 
Karl
2014/09/17 22:07:19
To try and make things clearer, I renamed ValIndex
 | 
| + if (!Ice::isScalarIntegerType(CondTy) || CondTy == Ice::IceType_i64) { | 
| 
Jim Stichnoth
2014/09/17 20:18:20
You can have a switch on an i64 type.
 
Karl
2014/09/17 22:07:18
Done.
 | 
| + 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]; | 
| + if (!isValidRecordSize(4 + NumCases * 4, "Function block switch")) | 
| + return; | 
| + Ice::InstSwitch *Switch = | 
| + Ice::InstSwitch::create(Func, NumCases, Cond, DefaultLabel); | 
| + unsigned ValIndex = 4; | 
| + for (unsigned CaseIndex = 0; CaseIndex < NumCases; ++CaseIndex) { | 
| + if (Values[ValIndex] != 1) { | 
| 
Jim Stichnoth
2014/09/17 20:18:20
(continuing comment from line 1695)
ValIndex can
 
Karl
2014/09/17 22:07:19
See comment above.
 | 
| + std::string Buffer; | 
| + raw_string_ostream StrBuf(Buffer); | 
| + StrBuf << "1 is expected for Values[" << ValIndex | 
| + << "] in switch record. Found: " << Values[ValIndex]; | 
| + Error(StrBuf.str()); | 
| + return; | 
| + } | 
| + if (Values[++ValIndex] != 1) { | 
| 
Jim Stichnoth
2014/09/17 20:18:20
Can this error test be combined with above?  E.g.
 
Karl
2014/09/17 22:07:19
Done.
 | 
| + std::string Buffer; | 
| + raw_string_ostream StrBuf(Buffer); | 
| + StrBuf << "1 is expected for Values[" << ValIndex | 
| + << "] in switch record. Found: " << Values[ValIndex]; | 
| + Error(StrBuf.str()); | 
| + return; | 
| + } | 
| + APInt Value(BitWidth, NaClDecodeSignRotatedValue(Values[++ValIndex]), | 
| + true); | 
| + Ice::CfgNode *Label = getBranchBasicBlock(Values[++ValIndex]); | 
| + Switch->addBranch(CaseIndex, Value.getSExtValue(), Label); | 
| + ++ValIndex; | 
| 
Jim Stichnoth
2014/09/17 20:18:20
(continuing comment from line 1721)
and this ++Va
 
Karl
2014/09/17 22:07:19
Removed.
 | 
| + } | 
| + CurrentNode->appendInst(Switch); | 
| + InstIsTerminating = true; | 
| + break; | 
| + } | 
| case naclbitc::FUNC_CODE_INST_UNREACHABLE: { | 
| // UNREACHABLE: [] | 
| if (!isValidRecordSize(0, "function block unreachable")) | 
| @@ -1781,11 +1843,10 @@ void FunctionParser::ProcessRecord() { | 
| // FORWARDTYPEREF: [opval, ty] | 
| if (!isValidRecordSize(2, "function block forward type ref")) | 
| return; | 
| - setOperand(Values[0], createInstVar( | 
| - Context->convertToIceType(Context->getTypeByID(Values[1])))); | 
| + setOperand(Values[0], createInstVar(Context->convertToIceType( | 
| + Context->getTypeByID(Values[1])))); | 
| break; | 
| } | 
| - case naclbitc::FUNC_CODE_INST_SWITCH: | 
| case naclbitc::FUNC_CODE_INST_CALL: | 
| case naclbitc::FUNC_CODE_INST_CALL_INDIRECT: | 
| default: |