Index: src/PNaClTranslator.cpp |
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp |
index f91437c6fa6cbc9d3ef43ca8a163561d479c5d7a..b9dac5552bbd39bfa2a693d7d8b4361c50f41797 100644 |
--- a/src/PNaClTranslator.cpp |
+++ b/src/PNaClTranslator.cpp |
@@ -1251,8 +1251,7 @@ public: |
Func->setFunctionName(FuncDecl->getName()); |
Func->setReturnType(Signature.getReturnType()); |
Func->setInternal(FuncDecl->getLinkage() == GlobalValue::InternalLinkage); |
- constexpr NaClBcIndexSize_t EntryBlock = 0; |
- CurrentNode = getBasicBlock(EntryBlock); |
+ CurrentNode = installNextBasicBlock(); |
Func->setEntryNode(CurrentNode); |
for (Ice::Type ArgType : Signature.getArgList()) { |
Func->addArg(getNextInstVar(ArgType)); |
@@ -1314,31 +1313,20 @@ 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::Operand *> OperandMap; |
- typedef std::unordered_map<NaClBcIndexSize_t, Ice::CfgNode *> CfgNodeMap; |
Ice::TimerMarker Timer; |
+ // The number of words in the bitstream defining the function block. |
+ uint64_t NumBytesDefiningFunction = 0; |
// 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 number of basic blocks declared for the function block. |
+ NaClBcIndexSize_t DeclaredNumberBbs = 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. |
@@ -1379,12 +1367,36 @@ private: |
void ProcessRecord() override; |
- void ExitBlock() override; |
+ void EnterBlock(unsigned NumWords) final { |
+ // Note: Bitstream defines words as 32-bit values. |
+ NumBytesDefiningFunction = NumWords * sizeof(uint32_t); |
+ } |
- bool verifyAndRenameBasicBlocks(); |
+ void ExitBlock() override; |
bool verifyAllForwardRefsDefined(); |
+ // Creates and appends a new basic block to the list of basic blocks. |
+ Ice::CfgNode *installNextBasicBlock() { |
+ assert(!isIRGenerationDisabled()); |
+ Ice::CfgNode *Node = Func->makeNode(); |
+ return Node; |
+ } |
+ |
+ // Returns the Index-th basic block in the list of basic blocks. |
+ Ice::CfgNode *getBasicBlock(NaClBcIndexSize_t Index) { |
+ assert(!isIRGenerationDisabled()); |
+ if (Index >= Func->getNumNodes()) { |
+ std::string Buffer; |
+ raw_string_ostream StrBuf(Buffer); |
+ StrBuf << "Reference to basic block " << Index |
+ << " not found. Must be less than " << Func->getNumNodes(); |
+ Error(StrBuf.str()); |
+ Index = 0; |
+ } |
+ return Func->getNodes()[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 |
@@ -1996,44 +2008,6 @@ bool FunctionParser::verifyAllForwardRefsDefined() { |
return false; |
} |
-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) { |
@@ -2043,12 +2017,18 @@ void FunctionParser::ExitBlock() { |
// Recover by inserting an unreachable instruction. |
CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get())); |
} |
+ ++CurrentBbIndex; |
+ if (CurrentBbIndex != DeclaredNumberBbs) { |
+ std::string Buffer; |
+ raw_string_ostream StrBuf(Buffer); |
+ StrBuf << "Function declared " << DeclaredNumberBbs |
+ << " basic blocks, but defined " << CurrentBbIndex << "."; |
+ Error(StrBuf.str()); |
+ } |
if (isIRGenerationDisabled()) |
return; |
if (!verifyAllForwardRefsDefined()) |
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; |
@@ -2082,8 +2062,9 @@ void FunctionParser::ProcessRecord() { |
const NaClBitcodeRecord::RecordVector &Values = Record.GetValues(); |
if (InstIsTerminating) { |
InstIsTerminating = false; |
+ ++CurrentBbIndex; |
if (!isIRGenerationDisabled()) |
- CurrentNode = getBasicBlock(++CurrentBbIndex); |
+ CurrentNode = getBasicBlock(CurrentBbIndex); |
} |
// The base index for relative indexing. |
NaClBcIndexSize_t BaseIndex = getNextInstIndex(); |
@@ -2092,24 +2073,40 @@ void FunctionParser::ProcessRecord() { |
// DECLAREBLOCKS: [n] |
if (!isValidRecordSize(1, "count")) |
return; |
- uint64_t NumBbsRaw = Values[0]; |
- if (NumBbsRaw == 0) { |
- Error("Functions must contain at least one basic block."); |
- NumBbsRaw = 1; |
- } else if (NumBbsRaw > NaClBcIndexSize_t_Max) { |
+ if (DeclaredNumberBbs > 0) { |
+ Error("Duplicate function block count record"); |
+ return; |
+ } |
+ |
+ uint64_t NumBbs = Values[0]; |
+ |
+ // Check for bad large sizes, since they can make ridiculous memory |
+ // requests and hang the user for large amounts of time. Note: We know |
+ // that each basic block must have a terminator instruction, and each |
+ // instruction is minimally defined by a two-bit abreviation. |
+ uint64_t MaxBbs = NumBytesDefiningFunction * (CHAR_BIT >> 1); |
+ if (NumBbs > MaxBbs) { |
std::string Buffer; |
raw_string_ostream StrBuf(Buffer); |
- StrBuf << "To many basic blocks specified: " << NumBbsRaw; |
+ StrBuf << "Function defines " << NumBbs |
+ << " basic blocks, which is too big for a function containing " |
+ << NumBytesDefiningFunction << " bytes"; |
Error(StrBuf.str()); |
- NumBbsRaw = NaClBcIndexSize_t_Max; |
+ NumBbs = MaxBbs; |
} |
+ |
+ if (NumBbs == 0) { |
+ Error("Functions must contain at least one basic block."); |
+ NumBbs = 1; |
+ } |
+ |
+ DeclaredNumberBbs = NumBbs; |
if (isIRGenerationDisabled()) |
return; |
- if (SpecifiedNumBbs != 0) { |
- Error("Duplicate function block count record"); |
- return; |
- } |
- SpecifiedNumBbs = NumBbsRaw; |
+ // Install the basic blocks, skipping bb0 which was created in the |
+ // constructor. |
+ for (size_t i = 1; i < NumBbs; ++i) |
+ installNextBasicBlock(); |
return; |
} |
case naclbitc::FUNC_CODE_INST_BINOP: { |
@@ -2933,9 +2930,13 @@ void FunctionValuesymtabParser::setBbName(NaClBcIndexSize_t Index, |
return; |
if (isIRGenerationDisabled()) |
return; |
- Ice::CfgNode *Bb = getFunctionParser()->getBasicBlock(Index); |
+ if (Index >= getFunctionParser()->getFunc()->getNumNodes()) { |
+ reportUnableToAssign("block", Index, Name); |
+ return; |
+ } |
std::string Nm(Name.data(), Name.size()); |
- Bb->setName(Nm); |
+ if (Ice::BuildDefs::dump()) |
+ getFunctionParser()->getFunc()->getNodes()[Index]->setName(Nm); |
} |
bool FunctionParser::ParseBlock(unsigned BlockID) { |