Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(840)

Side by Side Diff: src/PNaClTranslator.cpp

Issue 1293923002: Restore function-local variables to use a vector. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix nit. Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tests_lit/parse_errs/Inputs/bad-var-fwdref.tbc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | tests_lit/parse_errs/Inputs/bad-var-fwdref.tbc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698