 Chromium Code Reviews
 Chromium Code Reviews Issue 1293923002:
  Restore function-local variables to use a vector.  (Closed) 
  Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
    
  
    Issue 1293923002:
  Restore function-local variables to use a vector.  (Closed) 
  Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master| OLD | NEW | 
|---|---|
| 1 //===- subzero/src/PNaClTranslator.cpp - ICE from bitcode -----------------===// | 1 //===- subzero/src/PNaClTranslator.cpp - ICE from bitcode -----------------===// | 
| 2 // | 2 // | 
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator | 
| 4 // | 4 // | 
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source | 
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. | 
| 7 // | 7 // | 
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// | 
| 9 /// | 9 /// | 
| 10 /// \file | 10 /// \file | 
| (...skipping 1296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1307 return nullptr; | 1307 return nullptr; | 
| 1308 std::string Buffer; | 1308 std::string Buffer; | 
| 1309 raw_string_ostream StrBuf(Buffer); | 1309 raw_string_ostream StrBuf(Buffer); | 
| 1310 StrBuf << "Value index " << Index << " not defined!"; | 1310 StrBuf << "Value index " << Index << " not defined!"; | 
| 1311 Fatal(StrBuf.str()); | 1311 Fatal(StrBuf.str()); | 
| 1312 } | 1312 } | 
| 1313 return Op; | 1313 return Op; | 
| 1314 } | 1314 } | 
| 1315 | 1315 | 
| 1316 private: | 1316 private: | 
| 1317 typedef std::unordered_map<NaClBcIndexSize_t, Ice::Operand *> OperandMap; | |
| 1318 | |
| 1319 Ice::TimerMarker Timer; | 1317 Ice::TimerMarker Timer; | 
| 1320 // The number of words in the bitstream defining the function block. | 1318 // The number of words in the bitstream defining the function block. | 
| 1321 uint64_t NumBytesDefiningFunction = 0; | 1319 uint64_t NumBytesDefiningFunction = 0; | 
| 1320 // Maximum number of records that can appear in the function block, based on | |
| 1321 // the number of bytes defining the function block. | |
| 1322 uint64_t MaxRecordsInBlock = 0; | |
| 1322 // The corresponding ICE function defined by the function block. | 1323 // The corresponding ICE function defined by the function block. | 
| 1323 std::unique_ptr<Ice::Cfg> Func; | 1324 std::unique_ptr<Ice::Cfg> Func; | 
| 1324 // The index to the current basic block being built. | 1325 // The index to the current basic block being built. | 
| 1325 NaClBcIndexSize_t CurrentBbIndex = 0; | 1326 NaClBcIndexSize_t CurrentBbIndex = 0; | 
| 1326 // The number of basic blocks declared for the function block. | 1327 // The number of basic blocks declared for the function block. | 
| 1327 NaClBcIndexSize_t DeclaredNumberBbs = 0; | 1328 NaClBcIndexSize_t DeclaredNumberBbs = 0; | 
| 1328 // The basic block being built. | 1329 // The basic block being built. | 
| 1329 Ice::CfgNode *CurrentNode = nullptr; | 1330 Ice::CfgNode *CurrentNode = nullptr; | 
| 1330 // The ID for the function. | 1331 // The ID for the function. | 
| 1331 NaClBcIndexSize_t FcnId; | 1332 NaClBcIndexSize_t FcnId; | 
| 1332 // The corresponding function declaration. | 1333 // The corresponding function declaration. | 
| 1333 Ice::FunctionDeclaration *FuncDecl; | 1334 Ice::FunctionDeclaration *FuncDecl; | 
| 1334 // Holds the dividing point between local and global absolute value indices. | 1335 // Holds the dividing point between local and global absolute value indices. | 
| 1335 size_t CachedNumGlobalValueIDs; | 1336 size_t CachedNumGlobalValueIDs; | 
| 1336 // Holds operands local to the function block, based on indices | 1337 // Holds operands local to the function block, based on indices | 
| 1337 // defined in the bitcode file. | 1338 // defined in the bitcode file. | 
| 1338 OperandMap LocalOperands; | 1339 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.
 | |
| 1339 // Holds the index within LocalOperands corresponding to the next | 1340 // Holds the index within LocalOperands corresponding to the next | 
| 1340 // instruction that generates a value. | 1341 // instruction that generates a value. | 
| 1341 NaClBcIndexSize_t NextLocalInstIndex; | 1342 NaClBcIndexSize_t NextLocalInstIndex; | 
| 1342 // True if the last processed instruction was a terminating | 1343 // True if the last processed instruction was a terminating | 
| 1343 // instruction. | 1344 // instruction. | 
| 1344 bool InstIsTerminating = false; | 1345 bool InstIsTerminating = false; | 
| 1345 // Upper limit of alignment power allowed by LLVM | 1346 // Upper limit of alignment power allowed by LLVM | 
| 1346 static const uint32_t AlignPowerLimit = 29; | 1347 static const uint32_t AlignPowerLimit = 29; | 
| 1347 | 1348 | 
| 1348 // Extracts the corresponding Alignment to use, given the AlignPower | 1349 // Extracts the corresponding Alignment to use, given the AlignPower | 
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1363 Alignment = 1; | 1364 Alignment = 1; | 
| 1364 } | 1365 } | 
| 1365 | 1366 | 
| 1366 bool ParseBlock(unsigned BlockID) override; | 1367 bool ParseBlock(unsigned BlockID) override; | 
| 1367 | 1368 | 
| 1368 void ProcessRecord() override; | 1369 void ProcessRecord() override; | 
| 1369 | 1370 | 
| 1370 void EnterBlock(unsigned NumWords) final { | 1371 void EnterBlock(unsigned NumWords) final { | 
| 1371 // Note: Bitstream defines words as 32-bit values. | 1372 // Note: Bitstream defines words as 32-bit values. | 
| 1372 NumBytesDefiningFunction = NumWords * sizeof(uint32_t); | 1373 NumBytesDefiningFunction = NumWords * sizeof(uint32_t); | 
| 1374 // We know that all records are minimally defined by a two-bit abreviation. | |
| 1375 MaxRecordsInBlock = NumBytesDefiningFunction * (CHAR_BIT >> 1); | |
| 1373 } | 1376 } | 
| 1374 | 1377 | 
| 1375 void ExitBlock() override; | 1378 void ExitBlock() override; | 
| 1376 | 1379 | 
| 1377 bool verifyAllForwardRefsDefined(); | |
| 1378 | |
| 1379 // Creates and appends a new basic block to the list of basic blocks. | 1380 // Creates and appends a new basic block to the list of basic blocks. | 
| 1380 Ice::CfgNode *installNextBasicBlock() { | 1381 Ice::CfgNode *installNextBasicBlock() { | 
| 1381 assert(!isIRGenerationDisabled()); | 1382 assert(!isIRGenerationDisabled()); | 
| 1382 Ice::CfgNode *Node = Func->makeNode(); | 1383 Ice::CfgNode *Node = Func->makeNode(); | 
| 1383 return Node; | 1384 return Node; | 
| 1384 } | 1385 } | 
| 1385 | 1386 | 
| 1386 // Returns the Index-th basic block in the list of basic blocks. | 1387 // Returns the Index-th basic block in the list of basic blocks. | 
| 1387 Ice::CfgNode *getBasicBlock(NaClBcIndexSize_t Index) { | 1388 Ice::CfgNode *getBasicBlock(NaClBcIndexSize_t Index) { | 
| 1388 assert(!isIRGenerationDisabled()); | 1389 assert(!isIRGenerationDisabled()); | 
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1462 return 0; | 1463 return 0; | 
| 1463 } | 1464 } | 
| 1464 return BaseIndex - Id; | 1465 return BaseIndex - Id; | 
| 1465 } | 1466 } | 
| 1466 | 1467 | 
| 1467 // Sets element Index (in the local operands list) to Op. | 1468 // Sets element Index (in the local operands list) to Op. | 
| 1468 void setOperand(NaClBcIndexSize_t Index, Ice::Operand *Op) { | 1469 void setOperand(NaClBcIndexSize_t Index, Ice::Operand *Op) { | 
| 1469 assert(Op || isIRGenerationDisabled()); | 1470 assert(Op || isIRGenerationDisabled()); | 
| 1470 // Check if simple push works. | 1471 // Check if simple push works. | 
| 1471 NaClBcIndexSize_t LocalIndex = Index - CachedNumGlobalValueIDs; | 1472 NaClBcIndexSize_t LocalIndex = Index - CachedNumGlobalValueIDs; | 
| 1472 | 1473 if (LocalIndex == LocalOperands.size()) { | 
| 1473 // If element not defined, set it. | 1474 LocalOperands.push_back(Op); | 
| 1474 Ice::Operand *&IndexedOp = LocalOperands[LocalIndex]; | |
| 1475 if (IndexedOp == nullptr) { | |
| 1476 IndexedOp = Op; | |
| 1477 return; | 1475 return; | 
| 1478 } | 1476 } | 
| 1479 | 1477 | 
| 1480 // See if forward reference matchers. | 1478 // Must be forward reference, expand vector to accommodate. | 
| 1481 if (IndexedOp == Op) | 1479 if (LocalIndex >= LocalOperands.size()) { | 
| 1480 if (LocalIndex > MaxRecordsInBlock) { | |
| 1481 std::string Buffer; | |
| 1482 raw_string_ostream StrBuf(Buffer); | |
| 1483 StrBuf << "Forward reference @" << Index << " too big. Have " | |
| 1484 << CachedNumGlobalValueIDs << " globals and function contains " | |
| 1485 << NumBytesDefiningFunction << " bytes"; | |
| 1486 Fatal(StrBuf.str()); | |
| 1487 // Recover by using index one beyond the maximal allowed. | |
| 1488 LocalIndex = MaxRecordsInBlock; | |
| 1489 } | |
| 1490 LocalOperands.resize(LocalIndex + 1); | |
| 1491 } | |
| 1492 | |
| 1493 // If element not defined, set it. | |
| 1494 Ice::Operand *OldOp = LocalOperands[LocalIndex]; | |
| 1495 if (OldOp == nullptr) { | |
| 1496 LocalOperands[LocalIndex] = Op; | |
| 1497 return; | |
| 1498 } | |
| 1499 | |
| 1500 // See if forward reference matches. | |
| 1501 if (OldOp == Op) | |
| 1482 return; | 1502 return; | 
| 1483 | 1503 | 
| 1484 // Error has occurred. | 1504 // Error has occurred. | 
| 1485 std::string Buffer; | 1505 std::string Buffer; | 
| 1486 raw_string_ostream StrBuf(Buffer); | 1506 raw_string_ostream StrBuf(Buffer); | 
| 1487 StrBuf << "Multiple definitions for index " << Index << ": " << *Op | 1507 StrBuf << "Multiple definitions for index " << Index << ": " << *Op | 
| 1488 << " and " << *IndexedOp; | 1508 << " and " << *OldOp; | 
| 1489 Error(StrBuf.str()); | 1509 Error(StrBuf.str()); | 
| 1490 IndexedOp = Op; | 1510 LocalOperands[LocalIndex] = Op; | 
| 1491 } | 1511 } | 
| 1492 | 1512 | 
| 1493 // Returns the relative operand (wrt to BaseIndex) referenced by | 1513 // Returns the relative operand (wrt to BaseIndex) referenced by | 
| 1494 // the given value Index. | 1514 // the given value Index. | 
| 1495 Ice::Operand *getRelativeOperand(NaClBcIndexSize_t Index, | 1515 Ice::Operand *getRelativeOperand(NaClBcIndexSize_t Index, | 
| 1496 NaClBcIndexSize_t BaseIndex) { | 1516 NaClBcIndexSize_t BaseIndex) { | 
| 1497 return getOperand(convertRelativeToAbsIndex(Index, BaseIndex)); | 1517 return getOperand(convertRelativeToAbsIndex(Index, BaseIndex)); | 
| 1498 } | 1518 } | 
| 1499 | 1519 | 
| 1500 // Returns the absolute index of the next value generating instruction. | 1520 // Returns the absolute index of the next value generating instruction. | 
| (...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1981 void appendErrorInstruction(Ice::Type Ty) { | 2001 void appendErrorInstruction(Ice::Type Ty) { | 
| 1982 // Note: we don't worry about downstream translation errors because | 2002 // Note: we don't worry about downstream translation errors because | 
| 1983 // the function will not be translated if any errors occur. | 2003 // the function will not be translated if any errors occur. | 
| 1984 if (Ty == Ice::IceType_void) | 2004 if (Ty == Ice::IceType_void) | 
| 1985 return; | 2005 return; | 
| 1986 Ice::Variable *Var = getNextInstVar(Ty); | 2006 Ice::Variable *Var = getNextInstVar(Ty); | 
| 1987 CurrentNode->appendInst(Ice::InstAssign::create(Func.get(), Var, Var)); | 2007 CurrentNode->appendInst(Ice::InstAssign::create(Func.get(), Var, Var)); | 
| 1988 } | 2008 } | 
| 1989 }; | 2009 }; | 
| 1990 | 2010 | 
| 1991 bool FunctionParser::verifyAllForwardRefsDefined() { | |
| 1992 NaClBcIndexSize_t NumInstructions = | |
| 1993 NextLocalInstIndex - CachedNumGlobalValueIDs; | |
| 1994 if (NumInstructions == LocalOperands.size()) | |
| 1995 return true; | |
| 1996 // Find undefined forward references and report. | |
| 1997 std::vector<NaClBcIndexSize_t> UndefinedFwdRefs; | |
| 1998 for (const OperandMap::value_type &Elmt : LocalOperands) | |
| 1999 if (Elmt.first >= NextLocalInstIndex) | |
| 2000 UndefinedFwdRefs.push_back(Elmt.first); | |
| 2001 std::sort(UndefinedFwdRefs.begin(), UndefinedFwdRefs.end()); | |
| 2002 for (const NaClBcIndexSize_t Index : UndefinedFwdRefs) { | |
| 2003 std::string Buffer; | |
| 2004 raw_string_ostream StrBuf(Buffer); | |
| 2005 StrBuf << "Instruction forward reference not defined: " << Index; | |
| 2006 Error(StrBuf.str()); | |
| 2007 } | |
| 2008 return false; | |
| 2009 } | |
| 2010 | |
| 2011 void FunctionParser::ExitBlock() { | 2011 void FunctionParser::ExitBlock() { | 
| 2012 // Check if the last instruction in the function was terminating. | 2012 // Check if the last instruction in the function was terminating. | 
| 2013 if (!InstIsTerminating) { | 2013 if (!InstIsTerminating) { | 
| 2014 Error("Last instruction in function not terminator"); | 2014 Error("Last instruction in function not terminator"); | 
| 2015 if (isIRGenerationDisabled()) | 2015 if (isIRGenerationDisabled()) | 
| 2016 return; | 2016 return; | 
| 2017 // Recover by inserting an unreachable instruction. | 2017 // Recover by inserting an unreachable instruction. | 
| 2018 CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get())); | 2018 CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get())); | 
| 2019 } | 2019 } | 
| 2020 ++CurrentBbIndex; | 2020 ++CurrentBbIndex; | 
| 2021 if (CurrentBbIndex != DeclaredNumberBbs) { | 2021 if (CurrentBbIndex != DeclaredNumberBbs) { | 
| 2022 std::string Buffer; | 2022 std::string Buffer; | 
| 2023 raw_string_ostream StrBuf(Buffer); | 2023 raw_string_ostream StrBuf(Buffer); | 
| 2024 StrBuf << "Function declared " << DeclaredNumberBbs | 2024 StrBuf << "Function declared " << DeclaredNumberBbs | 
| 2025 << " basic blocks, but defined " << CurrentBbIndex << "."; | 2025 << " basic blocks, but defined " << CurrentBbIndex << "."; | 
| 2026 Error(StrBuf.str()); | 2026 Error(StrBuf.str()); | 
| 2027 } | 2027 } | 
| 2028 if (isIRGenerationDisabled()) | 2028 if (isIRGenerationDisabled()) | 
| 2029 return; | 2029 return; | 
| 2030 if (!verifyAllForwardRefsDefined()) | |
| 2031 return; | |
| 2032 // Before translating, check for blocks without instructions, and | 2030 // Before translating, check for blocks without instructions, and | 
| 2033 // insert unreachable. This shouldn't happen, but be safe. | 2031 // insert unreachable. This shouldn't happen, but be safe. | 
| 2034 size_t Index = 0; | 2032 size_t Index = 0; | 
| 2035 for (Ice::CfgNode *Node : Func->getNodes()) { | 2033 for (Ice::CfgNode *Node : Func->getNodes()) { | 
| 2036 if (Node->getInsts().empty()) { | 2034 if (Node->getInsts().empty()) { | 
| 2037 std::string Buffer; | 2035 std::string Buffer; | 
| 2038 raw_string_ostream StrBuf(Buffer); | 2036 raw_string_ostream StrBuf(Buffer); | 
| 2039 StrBuf << "Basic block " << Index << " contains no instructions"; | 2037 StrBuf << "Basic block " << Index << " contains no instructions"; | 
| 2040 Error(StrBuf.str()); | 2038 Error(StrBuf.str()); | 
| 2041 Node->appendInst(Ice::InstUnreachable::create(Func.get())); | 2039 Node->appendInst(Ice::InstUnreachable::create(Func.get())); | 
| (...skipping 29 matching lines...) Expand all Loading... | |
| 2071 switch (Record.GetCode()) { | 2069 switch (Record.GetCode()) { | 
| 2072 case naclbitc::FUNC_CODE_DECLAREBLOCKS: { | 2070 case naclbitc::FUNC_CODE_DECLAREBLOCKS: { | 
| 2073 // DECLAREBLOCKS: [n] | 2071 // DECLAREBLOCKS: [n] | 
| 2074 if (!isValidRecordSize(1, "count")) | 2072 if (!isValidRecordSize(1, "count")) | 
| 2075 return; | 2073 return; | 
| 2076 if (DeclaredNumberBbs > 0) { | 2074 if (DeclaredNumberBbs > 0) { | 
| 2077 Error("Duplicate function block count record"); | 2075 Error("Duplicate function block count record"); | 
| 2078 return; | 2076 return; | 
| 2079 } | 2077 } | 
| 2080 | 2078 | 
| 2079 // Check for bad large sizes, since they can make ridiculous memory | |
| 2080 // requests and hang the user for large amounts of time. | |
| 2081 uint64_t NumBbs = Values[0]; | 2081 uint64_t NumBbs = Values[0]; | 
| 2082 | 2082 if (NumBbs > MaxRecordsInBlock) { | 
| 2083 // Check for bad large sizes, since they can make ridiculous memory | |
| 2084 // requests and hang the user for large amounts of time. Note: We know | |
| 2085 // that each basic block must have a terminator instruction, and each | |
| 2086 // instruction is minimally defined by a two-bit abreviation. | |
| 2087 uint64_t MaxBbs = NumBytesDefiningFunction * (CHAR_BIT >> 1); | |
| 2088 if (NumBbs > MaxBbs) { | |
| 2089 std::string Buffer; | 2083 std::string Buffer; | 
| 2090 raw_string_ostream StrBuf(Buffer); | 2084 raw_string_ostream StrBuf(Buffer); | 
| 2091 StrBuf << "Function defines " << NumBbs | 2085 StrBuf << "Function defines " << NumBbs | 
| 2092 << " basic blocks, which is too big for a function containing " | 2086 << " basic blocks, which is too big for a function containing " | 
| 2093 << NumBytesDefiningFunction << " bytes"; | 2087 << NumBytesDefiningFunction << " bytes"; | 
| 2094 Error(StrBuf.str()); | 2088 Error(StrBuf.str()); | 
| 2095 NumBbs = MaxBbs; | 2089 NumBbs = MaxRecordsInBlock; | 
| 2096 } | 2090 } | 
| 2097 | 2091 | 
| 2098 if (NumBbs == 0) { | 2092 if (NumBbs == 0) { | 
| 2099 Error("Functions must contain at least one basic block."); | 2093 Error("Functions must contain at least one basic block."); | 
| 2100 NumBbs = 1; | 2094 NumBbs = 1; | 
| 2101 } | 2095 } | 
| 2102 | 2096 | 
| 2103 DeclaredNumberBbs = NumBbs; | 2097 DeclaredNumberBbs = NumBbs; | 
| 2104 if (isIRGenerationDisabled()) | 2098 if (isIRGenerationDisabled()) | 
| 2105 return; | 2099 return; | 
| (...skipping 1069 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3175 } | 3169 } | 
| 3176 if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) { | 3170 if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) { | 
| 3177 ErrStream | 3171 ErrStream | 
| 3178 << IRFilename | 3172 << IRFilename | 
| 3179 << ": Bitcode stream should be a multiple of 4 bytes in length.\n"; | 3173 << ": Bitcode stream should be a multiple of 4 bytes in length.\n"; | 
| 3180 llvm::report_fatal_error("Bitcode stream should be a multiple of 4 bytes"); | 3174 llvm::report_fatal_error("Bitcode stream should be a multiple of 4 bytes"); | 
| 3181 } | 3175 } | 
| 3182 } | 3176 } | 
| 3183 | 3177 | 
| 3184 } // end of namespace Ice | 3178 } // end of namespace Ice | 
| OLD | NEW |