| Index: src/PNaClTranslator.cpp
|
| diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp
|
| index 11e0b8e3997e1fd7bc28fca0c3126fd9ffcd745f..6ff9d97929ba5bc5d48ac61738786cd3e150bbc2 100644
|
| --- a/src/PNaClTranslator.cpp
|
| +++ b/src/PNaClTranslator.cpp
|
| @@ -1215,7 +1215,8 @@ public:
|
| Func->setFunctionName(FuncDecl->getName());
|
| Func->setReturnType(Signature.getReturnType());
|
| Func->setInternal(FuncDecl->getLinkage() == GlobalValue::InternalLinkage);
|
| - CurrentNode = installNextBasicBlock();
|
| + constexpr NaClBcIndexSize_t EntryBlock = 0;
|
| + CurrentNode = getBasicBlock(EntryBlock);
|
| Func->setEntryNode(CurrentNode);
|
| for (Ice::Type ArgType : Signature.getArgList()) {
|
| Func->addArg(getNextInstVar(ArgType));
|
| @@ -1283,14 +1284,30 @@ public:
|
| return Op;
|
| }
|
|
|
| + // Returns the Index-th basic block in the list of basic blocks.
|
| + Ice::CfgNode *getBasicBlock(NaClBcIndexSize_t Index) {
|
| + assert(!isIRGenerationDisabled());
|
| + Ice::CfgNode *&Node = BbMap[Index];
|
| + if (Node == nullptr)
|
| + Node = Func->makeNode();
|
| + return Node;
|
| + }
|
| +
|
| private:
|
| + typedef std::unordered_map<NaClBcIndexSize_t, Ice::CfgNode *> CfgNodeMap;
|
| +
|
| Ice::TimerMarker Timer;
|
| // The corresponding ICE function defined by the function block.
|
| std::unique_ptr<Ice::Cfg> Func;
|
| + // The specified number of basic blocks in the bitcode file.
|
| + NaClBcIndexSize_t SpecifiedNumBbs = 0;
|
| // The index to the current basic block being built.
|
| NaClBcIndexSize_t CurrentBbIndex = 0;
|
| // The basic block being built.
|
| Ice::CfgNode *CurrentNode = nullptr;
|
| + // Map from basic block id (as defined in the bitcode file) to
|
| + // the corresponding basic block that implements it.
|
| + CfgNodeMap BbMap;
|
| // The ID for the function.
|
| NaClBcIndexSize_t FcnId;
|
| // The corresponding function declaration.
|
| @@ -1333,27 +1350,7 @@ private:
|
|
|
| void ExitBlock() override;
|
|
|
| - // Creates and appends a new basic block to the list of basic blocks.
|
| - Ice::CfgNode *installNextBasicBlock() {
|
| - assert(!isIRGenerationDisabled());
|
| - return Func->makeNode();
|
| - }
|
| -
|
| - // Returns the Index-th basic block in the list of basic blocks.
|
| - Ice::CfgNode *getBasicBlock(NaClBcIndexSize_t Index) {
|
| - assert(!isIRGenerationDisabled());
|
| - const Ice::NodeList &Nodes = Func->getNodes();
|
| - if (Index >= Nodes.size()) {
|
| - std::string Buffer;
|
| - raw_string_ostream StrBuf(Buffer);
|
| - StrBuf << "Reference to basic block " << Index
|
| - << " not found. Must be less than " << Nodes.size();
|
| - Error(StrBuf.str());
|
| - // TODO(kschimpf) Remove error recovery once implementation complete.
|
| - Index = 0;
|
| - }
|
| - return Nodes[Index];
|
| - }
|
| + bool verifyAndRenameBasicBlocks();
|
|
|
| // Returns the Index-th basic block in the list of basic blocks.
|
| // Assumes Index corresponds to a branch instruction. Hence, if
|
| @@ -1961,6 +1958,44 @@ private:
|
| }
|
| };
|
|
|
| +bool FunctionParser::verifyAndRenameBasicBlocks() {
|
| + const size_t NumFoundBbs = BbMap.size();
|
| + // Verify number of basic blocks found match amount specified in function.
|
| + if (NumFoundBbs != SpecifiedNumBbs) {
|
| + std::string Buffer;
|
| + raw_string_ostream StrBuf(Buffer);
|
| + StrBuf << "Function specified " << SpecifiedNumBbs
|
| + << "basic blocks. Found: " << NumFoundBbs;
|
| + Error(StrBuf.str());
|
| + return false;
|
| + }
|
| + // Verify size limit allowed for basic blocks.
|
| + if (NumFoundBbs > NaClBcIndexSize_t_Max) {
|
| + std::string Buffer;
|
| + raw_string_ostream StrBuf(Buffer);
|
| + StrBuf << "Functions can't define more than " << NaClBcIndexSize_t_Max
|
| + << "basic blocks. Found: " << NumFoundBbs;
|
| + Error(StrBuf.str());
|
| + return false;
|
| + }
|
| + // Sort list of Bbs, verifying that no basic blocks are missing.
|
| + Ice::NodeList SortedBbs;
|
| + for (size_t i = 0; i < NumFoundBbs; ++i) {
|
| + CfgNodeMap::iterator pos = BbMap.find(i);
|
| + if (pos == BbMap.end()) {
|
| + std::string Buffer;
|
| + raw_string_ostream StrBuf(Buffer);
|
| + StrBuf << "Can't find definition for basic block " << i << ".";
|
| + Error(StrBuf.str());
|
| + return false;
|
| + }
|
| + SortedBbs.push_back(pos->second);
|
| + }
|
| + // Install sorted basic blocks.
|
| + Func->swapNodes(SortedBbs);
|
| + return true;
|
| +}
|
| +
|
| void FunctionParser::ExitBlock() {
|
| // Check if the last instruction in the function was terminating.
|
| if (!InstIsTerminating) {
|
| @@ -1972,6 +2007,8 @@ void FunctionParser::ExitBlock() {
|
| }
|
| if (isIRGenerationDisabled())
|
| return;
|
| + if (!verifyAndRenameBasicBlocks())
|
| + return;
|
| // Before translating, check for blocks without instructions, and
|
| // insert unreachable. This shouldn't happen, but be safe.
|
| size_t Index = 0;
|
| @@ -2030,14 +2067,11 @@ void FunctionParser::ProcessRecord() {
|
| }
|
| if (isIRGenerationDisabled())
|
| return;
|
| - if (Func->getNodes().size() != 1) {
|
| + if (SpecifiedNumBbs != 0) {
|
| Error("Duplicate function block count record");
|
| return;
|
| }
|
| - // Install the basic blocks, skipping bb0 which was created in the
|
| - // constructor.
|
| - for (size_t i = 1, NumBbs = NumBbsRaw; i < NumBbs; ++i)
|
| - installNextBasicBlock();
|
| + SpecifiedNumBbs = NumBbsRaw;
|
| return;
|
| }
|
| case naclbitc::FUNC_CODE_INST_BINOP: {
|
| @@ -2861,15 +2895,13 @@ void FunctionValuesymtabParser::setValueName(NaClBcIndexSize_t Index,
|
|
|
| void FunctionValuesymtabParser::setBbName(NaClBcIndexSize_t Index,
|
| StringType &Name) {
|
| - if (isIRGenerationDisabled())
|
| + if (!Ice::BuildDefs::dump())
|
| return;
|
| - if (Index >= getFunctionParser()->getFunc()->getNumNodes()) {
|
| - reportUnableToAssign("block", Index, Name);
|
| + if (isIRGenerationDisabled())
|
| return;
|
| - }
|
| + Ice::CfgNode *Bb = getFunctionParser()->getBasicBlock(Index);
|
| std::string Nm(Name.data(), Name.size());
|
| - if (Ice::BuildDefs::dump())
|
| - getFunctionParser()->getFunc()->getNodes()[Index]->setName(Nm);
|
| + Bb->setName(Nm);
|
| }
|
|
|
| bool FunctionParser::ParseBlock(unsigned BlockID) {
|
|
|