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 1288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1299 | 1299 |
1300 // Set the next constant ID to the given constant C. | 1300 // Set the next constant ID to the given constant C. |
1301 void setNextConstantID(Ice::Constant *C) { setNextLocalInstIndex(C); } | 1301 void setNextConstantID(Ice::Constant *C) { setNextLocalInstIndex(C); } |
1302 | 1302 |
1303 // Returns the value referenced by the given value Index. | 1303 // Returns the value referenced by the given value Index. |
1304 Ice::Operand *getOperand(NaClBcIndexSize_t Index) { | 1304 Ice::Operand *getOperand(NaClBcIndexSize_t Index) { |
1305 if (Index < CachedNumGlobalValueIDs) { | 1305 if (Index < CachedNumGlobalValueIDs) { |
1306 return Context->getGlobalConstantByID(Index); | 1306 return Context->getGlobalConstantByID(Index); |
1307 } | 1307 } |
1308 NaClBcIndexSize_t LocalIndex = Index - CachedNumGlobalValueIDs; | 1308 NaClBcIndexSize_t LocalIndex = Index - CachedNumGlobalValueIDs; |
1309 if (LocalIndex >= LocalOperands.size()) { | |
1310 std::string Buffer; | |
1311 raw_string_ostream StrBuf(Buffer); | |
1312 StrBuf << "Value index " << Index << " not defined!"; | |
1313 Fatal(StrBuf.str()); | |
1314 } | |
1315 Ice::Operand *Op = LocalOperands[LocalIndex]; | 1309 Ice::Operand *Op = LocalOperands[LocalIndex]; |
1316 if (Op == nullptr) { | 1310 if (Op == nullptr) { |
1317 if (isIRGenerationDisabled()) | 1311 if (isIRGenerationDisabled()) |
1318 return nullptr; | 1312 return nullptr; |
1319 std::string Buffer; | 1313 std::string Buffer; |
1320 raw_string_ostream StrBuf(Buffer); | 1314 raw_string_ostream StrBuf(Buffer); |
1321 StrBuf << "Value index " << Index << " not defined!"; | 1315 StrBuf << "Value index " << Index << " not defined!"; |
1322 Fatal(StrBuf.str()); | 1316 Fatal(StrBuf.str()); |
1323 } | 1317 } |
1324 return Op; | 1318 return Op; |
1325 } | 1319 } |
1326 | 1320 |
1327 // Returns the Index-th basic block in the list of basic blocks. | 1321 // Returns the Index-th basic block in the list of basic blocks. |
1328 Ice::CfgNode *getBasicBlock(NaClBcIndexSize_t Index) { | 1322 Ice::CfgNode *getBasicBlock(NaClBcIndexSize_t Index) { |
1329 assert(!isIRGenerationDisabled()); | 1323 assert(!isIRGenerationDisabled()); |
1330 Ice::CfgNode *&Node = BbMap[Index]; | 1324 Ice::CfgNode *&Node = BbMap[Index]; |
1331 if (Node == nullptr) | 1325 if (Node == nullptr) |
1332 Node = Func->makeNode(); | 1326 Node = Func->makeNode(); |
1333 return Node; | 1327 return Node; |
1334 } | 1328 } |
1335 | 1329 |
1336 private: | 1330 private: |
| 1331 typedef std::unordered_map<NaClBcIndexSize_t, Ice::Operand *> OperandMap; |
1337 typedef std::unordered_map<NaClBcIndexSize_t, Ice::CfgNode *> CfgNodeMap; | 1332 typedef std::unordered_map<NaClBcIndexSize_t, Ice::CfgNode *> CfgNodeMap; |
1338 | 1333 |
1339 Ice::TimerMarker Timer; | 1334 Ice::TimerMarker Timer; |
1340 // The corresponding ICE function defined by the function block. | 1335 // The corresponding ICE function defined by the function block. |
1341 std::unique_ptr<Ice::Cfg> Func; | 1336 std::unique_ptr<Ice::Cfg> Func; |
1342 // The specified number of basic blocks in the bitcode file. | 1337 // The specified number of basic blocks in the bitcode file. |
1343 NaClBcIndexSize_t SpecifiedNumBbs = 0; | 1338 NaClBcIndexSize_t SpecifiedNumBbs = 0; |
1344 // The index to the current basic block being built. | 1339 // The index to the current basic block being built. |
1345 NaClBcIndexSize_t CurrentBbIndex = 0; | 1340 NaClBcIndexSize_t CurrentBbIndex = 0; |
1346 // The basic block being built. | 1341 // The basic block being built. |
1347 Ice::CfgNode *CurrentNode = nullptr; | 1342 Ice::CfgNode *CurrentNode = nullptr; |
1348 // Map from basic block id (as defined in the bitcode file) to | 1343 // Map from basic block id (as defined in the bitcode file) to |
1349 // the corresponding basic block that implements it. | 1344 // the corresponding basic block that implements it. |
1350 CfgNodeMap BbMap; | 1345 CfgNodeMap BbMap; |
1351 // The ID for the function. | 1346 // The ID for the function. |
1352 NaClBcIndexSize_t FcnId; | 1347 NaClBcIndexSize_t FcnId; |
1353 // The corresponding function declaration. | 1348 // The corresponding function declaration. |
1354 Ice::FunctionDeclaration *FuncDecl; | 1349 Ice::FunctionDeclaration *FuncDecl; |
1355 // Holds the dividing point between local and global absolute value indices. | 1350 // Holds the dividing point between local and global absolute value indices. |
1356 size_t CachedNumGlobalValueIDs; | 1351 size_t CachedNumGlobalValueIDs; |
1357 // Holds operands local to the function block, based on indices | 1352 // Holds operands local to the function block, based on indices |
1358 // defined in the bitcode file. | 1353 // defined in the bitcode file. |
1359 std::vector<Ice::Operand *> LocalOperands; | 1354 OperandMap LocalOperands; |
1360 // Holds the index within LocalOperands corresponding to the next | 1355 // Holds the index within LocalOperands corresponding to the next |
1361 // instruction that generates a value. | 1356 // instruction that generates a value. |
1362 NaClBcIndexSize_t NextLocalInstIndex; | 1357 NaClBcIndexSize_t NextLocalInstIndex; |
1363 // True if the last processed instruction was a terminating | 1358 // True if the last processed instruction was a terminating |
1364 // instruction. | 1359 // instruction. |
1365 bool InstIsTerminating = false; | 1360 bool InstIsTerminating = false; |
1366 // Upper limit of alignment power allowed by LLVM | 1361 // Upper limit of alignment power allowed by LLVM |
1367 static const uint32_t AlignPowerLimit = 29; | 1362 static const uint32_t AlignPowerLimit = 29; |
1368 | 1363 |
1369 // Extracts the corresponding Alignment to use, given the AlignPower | 1364 // Extracts the corresponding Alignment to use, given the AlignPower |
(...skipping 15 matching lines...) Expand all Loading... |
1385 } | 1380 } |
1386 | 1381 |
1387 bool ParseBlock(unsigned BlockID) override; | 1382 bool ParseBlock(unsigned BlockID) override; |
1388 | 1383 |
1389 void ProcessRecord() override; | 1384 void ProcessRecord() override; |
1390 | 1385 |
1391 void ExitBlock() override; | 1386 void ExitBlock() override; |
1392 | 1387 |
1393 bool verifyAndRenameBasicBlocks(); | 1388 bool verifyAndRenameBasicBlocks(); |
1394 | 1389 |
| 1390 bool verifyAllForwardRefsDefined(); |
| 1391 |
1395 // Returns the Index-th basic block in the list of basic blocks. | 1392 // Returns the Index-th basic block in the list of basic blocks. |
1396 // Assumes Index corresponds to a branch instruction. Hence, if | 1393 // Assumes Index corresponds to a branch instruction. Hence, if |
1397 // the branch references the entry block, it also generates a | 1394 // the branch references the entry block, it also generates a |
1398 // corresponding error. | 1395 // corresponding error. |
1399 Ice::CfgNode *getBranchBasicBlock(NaClBcIndexSize_t Index) { | 1396 Ice::CfgNode *getBranchBasicBlock(NaClBcIndexSize_t Index) { |
1400 assert(!isIRGenerationDisabled()); | 1397 assert(!isIRGenerationDisabled()); |
1401 if (Index == 0) { | 1398 if (Index == 0) { |
1402 Error("Branch to entry block not allowed"); | 1399 Error("Branch to entry block not allowed"); |
1403 // TODO(kschimpf) Remove error recovery once implementation complete. | 1400 // TODO(kschimpf) Remove error recovery once implementation complete. |
1404 } | 1401 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1460 return 0; | 1457 return 0; |
1461 } | 1458 } |
1462 return BaseIndex - Id; | 1459 return BaseIndex - Id; |
1463 } | 1460 } |
1464 | 1461 |
1465 // Sets element Index (in the local operands list) to Op. | 1462 // Sets element Index (in the local operands list) to Op. |
1466 void setOperand(NaClBcIndexSize_t Index, Ice::Operand *Op) { | 1463 void setOperand(NaClBcIndexSize_t Index, Ice::Operand *Op) { |
1467 assert(Op || isIRGenerationDisabled()); | 1464 assert(Op || isIRGenerationDisabled()); |
1468 // Check if simple push works. | 1465 // Check if simple push works. |
1469 NaClBcIndexSize_t LocalIndex = Index - CachedNumGlobalValueIDs; | 1466 NaClBcIndexSize_t LocalIndex = Index - CachedNumGlobalValueIDs; |
1470 if (LocalIndex == LocalOperands.size()) { | 1467 |
1471 LocalOperands.push_back(Op); | 1468 // If element not defined, set it. |
| 1469 Ice::Operand *&IndexedOp = LocalOperands[LocalIndex]; |
| 1470 if (IndexedOp == nullptr) { |
| 1471 IndexedOp = Op; |
1472 return; | 1472 return; |
1473 } | 1473 } |
1474 | 1474 |
1475 // Must be forward reference, expand vector to accommodate. | 1475 // See if forward reference matchers. |
1476 if (LocalIndex >= LocalOperands.size()) | 1476 if (IndexedOp == Op) |
1477 LocalOperands.resize(LocalIndex + 1); | |
1478 | |
1479 // If element not defined, set it. | |
1480 Ice::Operand *OldOp = LocalOperands[LocalIndex]; | |
1481 if (OldOp == nullptr) { | |
1482 LocalOperands[LocalIndex] = Op; | |
1483 return; | |
1484 } | |
1485 | |
1486 // See if forward reference matches. | |
1487 if (OldOp == Op) | |
1488 return; | 1477 return; |
1489 | 1478 |
1490 // Error has occurred. | 1479 // Error has occurred. |
1491 std::string Buffer; | 1480 std::string Buffer; |
1492 raw_string_ostream StrBuf(Buffer); | 1481 raw_string_ostream StrBuf(Buffer); |
1493 StrBuf << "Multiple definitions for index " << Index << ": " << *Op | 1482 StrBuf << "Multiple definitions for index " << Index << ": " << *Op |
1494 << " and " << *OldOp; | 1483 << " and " << *IndexedOp; |
1495 Error(StrBuf.str()); | 1484 Error(StrBuf.str()); |
1496 // TODO(kschimpf) Remove error recovery once implementation complete. | 1485 // TODO(kschimpf) Remove error recovery once implementation complete. |
1497 LocalOperands[LocalIndex] = Op; | 1486 IndexedOp = Op; |
1498 } | 1487 } |
1499 | 1488 |
1500 // Returns the relative operand (wrt to BaseIndex) referenced by | 1489 // Returns the relative operand (wrt to BaseIndex) referenced by |
1501 // the given value Index. | 1490 // the given value Index. |
1502 Ice::Operand *getRelativeOperand(NaClBcIndexSize_t Index, | 1491 Ice::Operand *getRelativeOperand(NaClBcIndexSize_t Index, |
1503 NaClBcIndexSize_t BaseIndex) { | 1492 NaClBcIndexSize_t BaseIndex) { |
1504 return getOperand(convertRelativeToAbsIndex(Index, BaseIndex)); | 1493 return getOperand(convertRelativeToAbsIndex(Index, BaseIndex)); |
1505 } | 1494 } |
1506 | 1495 |
1507 // Returns the absolute index of the next value generating instruction. | 1496 // Returns the absolute index of the next value generating instruction. |
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1991 void appendErrorInstruction(Ice::Type Ty) { | 1980 void appendErrorInstruction(Ice::Type Ty) { |
1992 // Note: we don't worry about downstream translation errors because | 1981 // Note: we don't worry about downstream translation errors because |
1993 // the function will not be translated if any errors occur. | 1982 // the function will not be translated if any errors occur. |
1994 if (Ty == Ice::IceType_void) | 1983 if (Ty == Ice::IceType_void) |
1995 return; | 1984 return; |
1996 Ice::Variable *Var = getNextInstVar(Ty); | 1985 Ice::Variable *Var = getNextInstVar(Ty); |
1997 CurrentNode->appendInst(Ice::InstAssign::create(Func.get(), Var, Var)); | 1986 CurrentNode->appendInst(Ice::InstAssign::create(Func.get(), Var, Var)); |
1998 } | 1987 } |
1999 }; | 1988 }; |
2000 | 1989 |
| 1990 bool FunctionParser::verifyAllForwardRefsDefined() { |
| 1991 NaClBcIndexSize_t NumInstructions = |
| 1992 NextLocalInstIndex - CachedNumGlobalValueIDs; |
| 1993 if (NumInstructions == LocalOperands.size()) |
| 1994 return true; |
| 1995 // Find undefined forward references and report. |
| 1996 std::vector<NaClBcIndexSize_t> UndefinedFwdRefs; |
| 1997 for (const OperandMap::value_type &Elmt : LocalOperands) |
| 1998 if (Elmt.first >= NextLocalInstIndex) |
| 1999 UndefinedFwdRefs.push_back(Elmt.first); |
| 2000 std::sort(UndefinedFwdRefs.begin(), UndefinedFwdRefs.end()); |
| 2001 for (const NaClBcIndexSize_t Index : UndefinedFwdRefs) { |
| 2002 std::string Buffer; |
| 2003 raw_string_ostream StrBuf(Buffer); |
| 2004 StrBuf << "Instruction forward reference not defined: " << Index; |
| 2005 Error(StrBuf.str()); |
| 2006 } |
| 2007 return false; |
| 2008 } |
| 2009 |
2001 bool FunctionParser::verifyAndRenameBasicBlocks() { | 2010 bool FunctionParser::verifyAndRenameBasicBlocks() { |
2002 const size_t NumFoundBbs = BbMap.size(); | 2011 const size_t NumFoundBbs = BbMap.size(); |
2003 // Verify number of basic blocks found match amount specified in function. | 2012 // Verify number of basic blocks found match amount specified in function. |
2004 if (NumFoundBbs != SpecifiedNumBbs) { | 2013 if (NumFoundBbs != SpecifiedNumBbs) { |
2005 std::string Buffer; | 2014 std::string Buffer; |
2006 raw_string_ostream StrBuf(Buffer); | 2015 raw_string_ostream StrBuf(Buffer); |
2007 StrBuf << "Function specified " << SpecifiedNumBbs | 2016 StrBuf << "Function specified " << SpecifiedNumBbs |
2008 << "basic blocks. Found: " << NumFoundBbs; | 2017 << "basic blocks. Found: " << NumFoundBbs; |
2009 Error(StrBuf.str()); | 2018 Error(StrBuf.str()); |
2010 return false; | 2019 return false; |
(...skipping 29 matching lines...) Expand all Loading... |
2040 // Check if the last instruction in the function was terminating. | 2049 // Check if the last instruction in the function was terminating. |
2041 if (!InstIsTerminating) { | 2050 if (!InstIsTerminating) { |
2042 Error("Last instruction in function not terminator"); | 2051 Error("Last instruction in function not terminator"); |
2043 if (isIRGenerationDisabled()) | 2052 if (isIRGenerationDisabled()) |
2044 return; | 2053 return; |
2045 // Recover by inserting an unreachable instruction. | 2054 // Recover by inserting an unreachable instruction. |
2046 CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get())); | 2055 CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get())); |
2047 } | 2056 } |
2048 if (isIRGenerationDisabled()) | 2057 if (isIRGenerationDisabled()) |
2049 return; | 2058 return; |
| 2059 if (!verifyAllForwardRefsDefined()) |
| 2060 return; |
2050 if (!verifyAndRenameBasicBlocks()) | 2061 if (!verifyAndRenameBasicBlocks()) |
2051 return; | 2062 return; |
2052 // Before translating, check for blocks without instructions, and | 2063 // Before translating, check for blocks without instructions, and |
2053 // insert unreachable. This shouldn't happen, but be safe. | 2064 // insert unreachable. This shouldn't happen, but be safe. |
2054 size_t Index = 0; | 2065 size_t Index = 0; |
2055 for (Ice::CfgNode *Node : Func->getNodes()) { | 2066 for (Ice::CfgNode *Node : Func->getNodes()) { |
2056 if (Node->getInsts().empty()) { | 2067 if (Node->getInsts().empty()) { |
2057 std::string Buffer; | 2068 std::string Buffer; |
2058 raw_string_ostream StrBuf(Buffer); | 2069 raw_string_ostream StrBuf(Buffer); |
2059 StrBuf << "Basic block " << Index << " contains no instructions"; | 2070 StrBuf << "Basic block " << Index << " contains no instructions"; |
(...skipping 1120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3180 } | 3191 } |
3181 if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) { | 3192 if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) { |
3182 ErrStream | 3193 ErrStream |
3183 << IRFilename | 3194 << IRFilename |
3184 << ": Bitcode stream should be a multiple of 4 bytes in length.\n"; | 3195 << ": Bitcode stream should be a multiple of 4 bytes in length.\n"; |
3185 llvm::report_fatal_error("Bitcode stream should be a multiple of 4 bytes"); | 3196 llvm::report_fatal_error("Bitcode stream should be a multiple of 4 bytes"); |
3186 } | 3197 } |
3187 } | 3198 } |
3188 | 3199 |
3189 } // end of namespace Ice | 3200 } // end of namespace Ice |
OLD | NEW |