Index: src/PNaClTranslator.cpp |
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp |
index 4d46d4d070f198a4b11a313f54625416419e06ee..e39288822a692a2040294b82dbec299dbc66cd9d 100644 |
--- a/src/PNaClTranslator.cpp |
+++ b/src/PNaClTranslator.cpp |
@@ -865,6 +865,18 @@ private: |
return Nodes[Index]; |
} |
+ // Returns the Index-th basic block in the list of basic blocks. |
+ // Assumes Index corresponds to a branch instruction. Hence, if |
+ // the branch references the entry block, it also generates a |
+ // corresponding error. |
+ Ice::CfgNode *getBranchBasicBlock(uint32_t Index) { |
+ if (Index == 0) { |
+ Error("Branch to entry block not allowed"); |
+ // TODO(kschimpf) Remove error recovery once implementation complete. |
+ } |
+ return GetBasicBlock(Index); |
+ } |
+ |
// Generates the next available local variable using the given |
// type. Note: if Ty is void, this function returns NULL. |
Ice::Variable *NextInstVar(Ice::Type Ty) { |
@@ -1105,7 +1117,12 @@ void FunctionParser::ExitBlock() { |
Node->appendInst(Ice::InstUnreachable::create(Func)); |
} |
} |
- getTranslator().translateFcn(Func); |
+ // Note: Once any errors have been found, we turn off all |
+ // translation of all remaining functions. This allows use to see |
+ // multiple errors, without adding extra checks to the translator |
+ // for such parsing errors. |
+ if (Context->getNumErrors() == 0) |
+ getTranslator().translateFcn(Func); |
} |
void FunctionParser::ReportInvalidBinaryOp(Ice::InstArithmetic::OpKind Op, |
@@ -1293,7 +1310,6 @@ void FunctionParser::ProcessRecord() { |
} |
case naclbitc::FUNC_CODE_INST_RET: { |
// RET: [opval?] |
- InstIsTerminating = true; |
if (!isValidRecordSizeInRange(0, 1, "function block ret")) |
return; |
if (Values.size() == 0) { |
@@ -1301,6 +1317,35 @@ void FunctionParser::ProcessRecord() { |
} else { |
Inst = Ice::InstRet::create(Func, getRelativeOperand(Values[0])); |
} |
+ InstIsTerminating = true; |
+ break; |
+ } |
+ case naclbitc::FUNC_CODE_INST_BR: { |
+ if (Values.size() == 1) { |
+ // BR: [bb#] |
+ Ice::CfgNode *Block = getBranchBasicBlock(Values[0]); |
+ if (Block == NULL) |
+ return; |
+ Inst = Ice::InstBr::create(Func, Block); |
+ } else { |
+ // BR: [bb#, bb#, opval] |
+ if (!isValidRecordSize(3, "function block branch")) |
+ return; |
+ Ice::Operand *Cond = getRelativeOperand(Values[2]); |
+ if (Cond->getType() != Ice::IceType_i1) { |
+ std::string Buffer; |
+ raw_string_ostream StrBuf(Buffer); |
+ StrBuf << "Branch condition not i1"; |
+ Error(StrBuf.str()); |
+ return; |
+ } |
+ Ice::CfgNode *ThenBlock = getBranchBasicBlock(Values[0]); |
+ Ice::CfgNode *ElseBlock = getBranchBasicBlock(Values[1]); |
+ if (ThenBlock == NULL || ElseBlock == NULL) |
+ return; |
+ Inst = Ice::InstBr::create(Func, Cond, ThenBlock, ElseBlock); |
+ } |
+ InstIsTerminating = true; |
break; |
} |
default: |