Chromium Code Reviews| Index: src/PNaClTranslator.cpp |
| diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp |
| index b9dac5552bbd39bfa2a693d7d8b4361c50f41797..7bbee75ab03525d6b2de0736e4de1b2493ff1ac8 100644 |
| --- a/src/PNaClTranslator.cpp |
| +++ b/src/PNaClTranslator.cpp |
| @@ -1314,11 +1314,12 @@ public: |
| } |
| private: |
| - typedef std::unordered_map<NaClBcIndexSize_t, Ice::Operand *> OperandMap; |
| - |
| Ice::TimerMarker Timer; |
| // The number of words in the bitstream defining the function block. |
| uint64_t NumBytesDefiningFunction = 0; |
| + // Maximum number of records that can appear in the function block, based on |
| + // the number of bytes defining the function block. |
| + uint64_t MaxRecordsInBlock = 0; |
| // The corresponding ICE function defined by the function block. |
| std::unique_ptr<Ice::Cfg> Func; |
| // The index to the current basic block being built. |
| @@ -1335,7 +1336,7 @@ private: |
| size_t CachedNumGlobalValueIDs; |
| // Holds operands local to the function block, based on indices |
| // defined in the bitcode file. |
| - OperandMap LocalOperands; |
| + std::vector<Ice::Operand *> LocalOperands; |
|
Jim Stichnoth
2015/08/17 19:41:03
It occurs to me that using STL containers with the
Karl
2015/08/17 19:47:34
Acknowledged.
|
| // Holds the index within LocalOperands corresponding to the next |
| // instruction that generates a value. |
| NaClBcIndexSize_t NextLocalInstIndex; |
| @@ -1370,12 +1371,12 @@ private: |
| void EnterBlock(unsigned NumWords) final { |
| // Note: Bitstream defines words as 32-bit values. |
| NumBytesDefiningFunction = NumWords * sizeof(uint32_t); |
| + // We know that all records are minimally defined by a two-bit abreviation. |
| + MaxRecordsInBlock = NumBytesDefiningFunction * (CHAR_BIT >> 1); |
| } |
| void ExitBlock() override; |
| - bool verifyAllForwardRefsDefined(); |
| - |
| // Creates and appends a new basic block to the list of basic blocks. |
| Ice::CfgNode *installNextBasicBlock() { |
| assert(!isIRGenerationDisabled()); |
| @@ -1469,25 +1470,44 @@ private: |
| assert(Op || isIRGenerationDisabled()); |
| // Check if simple push works. |
| NaClBcIndexSize_t LocalIndex = Index - CachedNumGlobalValueIDs; |
| + if (LocalIndex == LocalOperands.size()) { |
| + LocalOperands.push_back(Op); |
| + return; |
| + } |
| + |
| + // Must be forward reference, expand vector to accommodate. |
| + if (LocalIndex >= LocalOperands.size()) { |
| + if (LocalIndex > MaxRecordsInBlock) { |
| + std::string Buffer; |
| + raw_string_ostream StrBuf(Buffer); |
| + StrBuf << "Forward reference @" << Index << " too big. Have " |
| + << CachedNumGlobalValueIDs << " globals and function contains " |
| + << NumBytesDefiningFunction << " bytes"; |
| + Fatal(StrBuf.str()); |
| + // Recover by using index one beyond the maximal allowed. |
| + LocalIndex = MaxRecordsInBlock; |
| + } |
| + LocalOperands.resize(LocalIndex + 1); |
| + } |
| // If element not defined, set it. |
| - Ice::Operand *&IndexedOp = LocalOperands[LocalIndex]; |
| - if (IndexedOp == nullptr) { |
| - IndexedOp = Op; |
| + Ice::Operand *OldOp = LocalOperands[LocalIndex]; |
| + if (OldOp == nullptr) { |
| + LocalOperands[LocalIndex] = Op; |
| return; |
| } |
| - // See if forward reference matchers. |
| - if (IndexedOp == Op) |
| + // See if forward reference matches. |
| + if (OldOp == Op) |
| return; |
| // Error has occurred. |
| std::string Buffer; |
| raw_string_ostream StrBuf(Buffer); |
| StrBuf << "Multiple definitions for index " << Index << ": " << *Op |
| - << " and " << *IndexedOp; |
| + << " and " << *OldOp; |
| Error(StrBuf.str()); |
| - IndexedOp = Op; |
| + LocalOperands[LocalIndex] = Op; |
| } |
| // Returns the relative operand (wrt to BaseIndex) referenced by |
| @@ -1988,26 +2008,6 @@ private: |
| } |
| }; |
| -bool FunctionParser::verifyAllForwardRefsDefined() { |
| - NaClBcIndexSize_t NumInstructions = |
| - NextLocalInstIndex - CachedNumGlobalValueIDs; |
| - if (NumInstructions == LocalOperands.size()) |
| - return true; |
| - // Find undefined forward references and report. |
| - std::vector<NaClBcIndexSize_t> UndefinedFwdRefs; |
| - for (const OperandMap::value_type &Elmt : LocalOperands) |
| - if (Elmt.first >= NextLocalInstIndex) |
| - UndefinedFwdRefs.push_back(Elmt.first); |
| - std::sort(UndefinedFwdRefs.begin(), UndefinedFwdRefs.end()); |
| - for (const NaClBcIndexSize_t Index : UndefinedFwdRefs) { |
| - std::string Buffer; |
| - raw_string_ostream StrBuf(Buffer); |
| - StrBuf << "Instruction forward reference not defined: " << Index; |
| - Error(StrBuf.str()); |
| - } |
| - return false; |
| -} |
| - |
| void FunctionParser::ExitBlock() { |
| // Check if the last instruction in the function was terminating. |
| if (!InstIsTerminating) { |
| @@ -2027,8 +2027,6 @@ void FunctionParser::ExitBlock() { |
| } |
| if (isIRGenerationDisabled()) |
| return; |
| - if (!verifyAllForwardRefsDefined()) |
| - return; |
| // Before translating, check for blocks without instructions, and |
| // insert unreachable. This shouldn't happen, but be safe. |
| size_t Index = 0; |
| @@ -2078,21 +2076,17 @@ void FunctionParser::ProcessRecord() { |
| 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) { |
| + // requests and hang the user for large amounts of time. |
| + uint64_t NumBbs = Values[0]; |
| + if (NumBbs > MaxRecordsInBlock) { |
| std::string Buffer; |
| raw_string_ostream StrBuf(Buffer); |
| StrBuf << "Function defines " << NumBbs |
| << " basic blocks, which is too big for a function containing " |
| << NumBytesDefiningFunction << " bytes"; |
| Error(StrBuf.str()); |
| - NumBbs = MaxBbs; |
| + NumBbs = MaxRecordsInBlock; |
| } |
| if (NumBbs == 0) { |