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 |