Chromium Code Reviews| 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 1248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1259 | 1259 |
| 1260 // Set the next constant ID to the given constant C. | 1260 // Set the next constant ID to the given constant C. |
| 1261 void setNextConstantID(Ice::Constant *C) { setNextLocalInstIndex(C); } | 1261 void setNextConstantID(Ice::Constant *C) { setNextLocalInstIndex(C); } |
| 1262 | 1262 |
| 1263 // Returns the value referenced by the given value Index. | 1263 // Returns the value referenced by the given value Index. |
| 1264 Ice::Operand *getOperand(NaClBcIndexSize_t Index) { | 1264 Ice::Operand *getOperand(NaClBcIndexSize_t Index) { |
| 1265 if (Index < CachedNumGlobalValueIDs) { | 1265 if (Index < CachedNumGlobalValueIDs) { |
| 1266 return Context->getGlobalConstantByID(Index); | 1266 return Context->getGlobalConstantByID(Index); |
| 1267 } | 1267 } |
| 1268 NaClBcIndexSize_t LocalIndex = Index - CachedNumGlobalValueIDs; | 1268 NaClBcIndexSize_t LocalIndex = Index - CachedNumGlobalValueIDs; |
| 1269 if (LocalIndex >= LocalOperands.size()) { | |
| 1270 std::string Buffer; | |
| 1271 raw_string_ostream StrBuf(Buffer); | |
| 1272 StrBuf << "Value index " << Index << " not defined!"; | |
| 1273 Fatal(StrBuf.str()); | |
| 1274 } | |
| 1275 Ice::Operand *Op = LocalOperands[LocalIndex]; | 1269 Ice::Operand *Op = LocalOperands[LocalIndex]; |
| 1276 if (Op == nullptr) { | 1270 if (Op == nullptr) { |
| 1277 if (isIRGenerationDisabled()) | 1271 if (isIRGenerationDisabled()) |
| 1278 return nullptr; | 1272 return nullptr; |
| 1279 std::string Buffer; | 1273 std::string Buffer; |
| 1280 raw_string_ostream StrBuf(Buffer); | 1274 raw_string_ostream StrBuf(Buffer); |
| 1281 StrBuf << "Value index " << Index << " not defined!"; | 1275 StrBuf << "Value index " << Index << " not defined!"; |
| 1282 Fatal(StrBuf.str()); | 1276 Fatal(StrBuf.str()); |
| 1283 } | 1277 } |
| 1284 return Op; | 1278 return Op; |
| 1285 } | 1279 } |
| 1286 | 1280 |
| 1287 // Returns the Index-th basic block in the list of basic blocks. | 1281 // Returns the Index-th basic block in the list of basic blocks. |
| 1288 Ice::CfgNode *getBasicBlock(NaClBcIndexSize_t Index) { | 1282 Ice::CfgNode *getBasicBlock(NaClBcIndexSize_t Index) { |
| 1289 assert(!isIRGenerationDisabled()); | 1283 assert(!isIRGenerationDisabled()); |
| 1290 Ice::CfgNode *&Node = BbMap[Index]; | 1284 Ice::CfgNode *&Node = BbMap[Index]; |
| 1291 if (Node == nullptr) | 1285 if (Node == nullptr) |
| 1292 Node = Func->makeNode(); | 1286 Node = Func->makeNode(); |
| 1293 return Node; | 1287 return Node; |
| 1294 } | 1288 } |
| 1295 | 1289 |
| 1296 private: | 1290 private: |
| 1291 typedef std::unordered_map<NaClBcIndexSize_t, Ice::Operand *> OperandsMap; | |
|
Jim Stichnoth
2015/08/08 16:14:48
For naming consistency, I would use "OperandMap" o
Karl
2015/08/10 18:13:09
Done.
| |
| 1297 typedef std::unordered_map<NaClBcIndexSize_t, Ice::CfgNode *> CfgNodeMap; | 1292 typedef std::unordered_map<NaClBcIndexSize_t, Ice::CfgNode *> CfgNodeMap; |
| 1298 | 1293 |
| 1299 Ice::TimerMarker Timer; | 1294 Ice::TimerMarker Timer; |
| 1300 // The corresponding ICE function defined by the function block. | 1295 // The corresponding ICE function defined by the function block. |
| 1301 std::unique_ptr<Ice::Cfg> Func; | 1296 std::unique_ptr<Ice::Cfg> Func; |
| 1302 // The specified number of basic blocks in the bitcode file. | 1297 // The specified number of basic blocks in the bitcode file. |
| 1303 NaClBcIndexSize_t SpecifiedNumBbs = 0; | 1298 NaClBcIndexSize_t SpecifiedNumBbs = 0; |
| 1304 // The index to the current basic block being built. | 1299 // The index to the current basic block being built. |
| 1305 NaClBcIndexSize_t CurrentBbIndex = 0; | 1300 NaClBcIndexSize_t CurrentBbIndex = 0; |
| 1306 // The basic block being built. | 1301 // The basic block being built. |
| 1307 Ice::CfgNode *CurrentNode = nullptr; | 1302 Ice::CfgNode *CurrentNode = nullptr; |
| 1308 // Map from basic block id (as defined in the bitcode file) to | 1303 // Map from basic block id (as defined in the bitcode file) to |
| 1309 // the corresponding basic block that implements it. | 1304 // the corresponding basic block that implements it. |
| 1310 CfgNodeMap BbMap; | 1305 CfgNodeMap BbMap; |
| 1311 // The ID for the function. | 1306 // The ID for the function. |
| 1312 NaClBcIndexSize_t FcnId; | 1307 NaClBcIndexSize_t FcnId; |
| 1313 // The corresponding function declaration. | 1308 // The corresponding function declaration. |
| 1314 Ice::FunctionDeclaration *FuncDecl; | 1309 Ice::FunctionDeclaration *FuncDecl; |
| 1315 // Holds the dividing point between local and global absolute value indices. | 1310 // Holds the dividing point between local and global absolute value indices. |
| 1316 size_t CachedNumGlobalValueIDs; | 1311 size_t CachedNumGlobalValueIDs; |
| 1317 // Holds operands local to the function block, based on indices | 1312 // Holds operands local to the function block, based on indices |
| 1318 // defined in the bitcode file. | 1313 // defined in the bitcode file. |
| 1319 std::vector<Ice::Operand *> LocalOperands; | 1314 OperandsMap LocalOperands; |
| 1320 // Holds the index within LocalOperands corresponding to the next | 1315 // Holds the index within LocalOperands corresponding to the next |
| 1321 // instruction that generates a value. | 1316 // instruction that generates a value. |
| 1322 NaClBcIndexSize_t NextLocalInstIndex; | 1317 NaClBcIndexSize_t NextLocalInstIndex; |
| 1323 // True if the last processed instruction was a terminating | 1318 // True if the last processed instruction was a terminating |
| 1324 // instruction. | 1319 // instruction. |
| 1325 bool InstIsTerminating = false; | 1320 bool InstIsTerminating = false; |
| 1326 // Upper limit of alignment power allowed by LLVM | 1321 // Upper limit of alignment power allowed by LLVM |
| 1327 static const uint32_t AlignPowerLimit = 29; | 1322 static const uint32_t AlignPowerLimit = 29; |
| 1328 | 1323 |
| 1329 // Extracts the corresponding Alignment to use, given the AlignPower | 1324 // Extracts the corresponding Alignment to use, given the AlignPower |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1345 } | 1340 } |
| 1346 | 1341 |
| 1347 bool ParseBlock(unsigned BlockID) override; | 1342 bool ParseBlock(unsigned BlockID) override; |
| 1348 | 1343 |
| 1349 void ProcessRecord() override; | 1344 void ProcessRecord() override; |
| 1350 | 1345 |
| 1351 void ExitBlock() override; | 1346 void ExitBlock() override; |
| 1352 | 1347 |
| 1353 bool verifyAndRenameBasicBlocks(); | 1348 bool verifyAndRenameBasicBlocks(); |
| 1354 | 1349 |
| 1350 bool verifyAllForwardRefsDefined(); | |
| 1351 | |
| 1355 // Returns the Index-th basic block in the list of basic blocks. | 1352 // Returns the Index-th basic block in the list of basic blocks. |
| 1356 // Assumes Index corresponds to a branch instruction. Hence, if | 1353 // Assumes Index corresponds to a branch instruction. Hence, if |
| 1357 // the branch references the entry block, it also generates a | 1354 // the branch references the entry block, it also generates a |
| 1358 // corresponding error. | 1355 // corresponding error. |
| 1359 Ice::CfgNode *getBranchBasicBlock(NaClBcIndexSize_t Index) { | 1356 Ice::CfgNode *getBranchBasicBlock(NaClBcIndexSize_t Index) { |
| 1360 assert(!isIRGenerationDisabled()); | 1357 assert(!isIRGenerationDisabled()); |
| 1361 if (Index == 0) { | 1358 if (Index == 0) { |
| 1362 Error("Branch to entry block not allowed"); | 1359 Error("Branch to entry block not allowed"); |
| 1363 // TODO(kschimpf) Remove error recovery once implementation complete. | 1360 // TODO(kschimpf) Remove error recovery once implementation complete. |
| 1364 } | 1361 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1420 return 0; | 1417 return 0; |
| 1421 } | 1418 } |
| 1422 return BaseIndex - Id; | 1419 return BaseIndex - Id; |
| 1423 } | 1420 } |
| 1424 | 1421 |
| 1425 // Sets element Index (in the local operands list) to Op. | 1422 // Sets element Index (in the local operands list) to Op. |
| 1426 void setOperand(NaClBcIndexSize_t Index, Ice::Operand *Op) { | 1423 void setOperand(NaClBcIndexSize_t Index, Ice::Operand *Op) { |
| 1427 assert(Op || isIRGenerationDisabled()); | 1424 assert(Op || isIRGenerationDisabled()); |
| 1428 // Check if simple push works. | 1425 // Check if simple push works. |
| 1429 NaClBcIndexSize_t LocalIndex = Index - CachedNumGlobalValueIDs; | 1426 NaClBcIndexSize_t LocalIndex = Index - CachedNumGlobalValueIDs; |
| 1430 if (LocalIndex == LocalOperands.size()) { | 1427 |
| 1431 LocalOperands.push_back(Op); | 1428 // If element not defined, set it. |
| 1429 Ice::Operand *&IndexedOp = LocalOperands[LocalIndex]; | |
| 1430 if (IndexedOp == nullptr) { | |
| 1431 IndexedOp = Op; | |
| 1432 return; | 1432 return; |
| 1433 } | 1433 } |
| 1434 | 1434 |
| 1435 // Must be forward reference, expand vector to accommodate. | 1435 // See if forward reference matchers. |
| 1436 if (LocalIndex >= LocalOperands.size()) | 1436 if (IndexedOp == Op) |
| 1437 LocalOperands.resize(LocalIndex + 1); | |
| 1438 | |
| 1439 // If element not defined, set it. | |
| 1440 Ice::Operand *OldOp = LocalOperands[LocalIndex]; | |
| 1441 if (OldOp == nullptr) { | |
| 1442 LocalOperands[LocalIndex] = Op; | |
| 1443 return; | |
| 1444 } | |
| 1445 | |
| 1446 // See if forward reference matches. | |
| 1447 if (OldOp == Op) | |
| 1448 return; | 1437 return; |
| 1449 | 1438 |
| 1450 // Error has occurred. | 1439 // Error has occurred. |
| 1451 std::string Buffer; | 1440 std::string Buffer; |
| 1452 raw_string_ostream StrBuf(Buffer); | 1441 raw_string_ostream StrBuf(Buffer); |
| 1453 StrBuf << "Multiple definitions for index " << Index << ": " << *Op | 1442 StrBuf << "Multiple definitions for index " << Index << ": " << *Op |
| 1454 << " and " << *OldOp; | 1443 << " and " << *IndexedOp; |
| 1455 Error(StrBuf.str()); | 1444 Error(StrBuf.str()); |
| 1456 // TODO(kschimpf) Remove error recovery once implementation complete. | 1445 // TODO(kschimpf) Remove error recovery once implementation complete. |
|
Jim Stichnoth
2015/08/08 16:14:48
Trying to remember the context of these TODOs...
Karl
2015/08/10 18:13:09
This was back when someone wasn't sure we should k
| |
| 1457 LocalOperands[LocalIndex] = Op; | 1446 IndexedOp = Op; |
| 1458 } | 1447 } |
| 1459 | 1448 |
| 1460 // Returns the relative operand (wrt to BaseIndex) referenced by | 1449 // Returns the relative operand (wrt to BaseIndex) referenced by |
| 1461 // the given value Index. | 1450 // the given value Index. |
| 1462 Ice::Operand *getRelativeOperand(NaClBcIndexSize_t Index, | 1451 Ice::Operand *getRelativeOperand(NaClBcIndexSize_t Index, |
| 1463 NaClBcIndexSize_t BaseIndex) { | 1452 NaClBcIndexSize_t BaseIndex) { |
| 1464 return getOperand(convertRelativeToAbsIndex(Index, BaseIndex)); | 1453 return getOperand(convertRelativeToAbsIndex(Index, BaseIndex)); |
| 1465 } | 1454 } |
| 1466 | 1455 |
| 1467 // Returns the absolute index of the next value generating instruction. | 1456 // Returns the absolute index of the next value generating instruction. |
| (...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1951 void appendErrorInstruction(Ice::Type Ty) { | 1940 void appendErrorInstruction(Ice::Type Ty) { |
| 1952 // Note: we don't worry about downstream translation errors because | 1941 // Note: we don't worry about downstream translation errors because |
| 1953 // the function will not be translated if any errors occur. | 1942 // the function will not be translated if any errors occur. |
| 1954 if (Ty == Ice::IceType_void) | 1943 if (Ty == Ice::IceType_void) |
| 1955 return; | 1944 return; |
| 1956 Ice::Variable *Var = getNextInstVar(Ty); | 1945 Ice::Variable *Var = getNextInstVar(Ty); |
| 1957 CurrentNode->appendInst(Ice::InstAssign::create(Func.get(), Var, Var)); | 1946 CurrentNode->appendInst(Ice::InstAssign::create(Func.get(), Var, Var)); |
| 1958 } | 1947 } |
| 1959 }; | 1948 }; |
| 1960 | 1949 |
| 1950 bool FunctionParser::verifyAllForwardRefsDefined() { | |
| 1951 NaClBcIndexSize_t NumInstructions = | |
| 1952 NextLocalInstIndex - CachedNumGlobalValueIDs; | |
| 1953 if (NumInstructions == LocalOperands.size()) | |
| 1954 return true; | |
| 1955 // Find undefined forward references and report. | |
| 1956 std::vector<NaClBcIndexSize_t> UndefinedFwdRefs; | |
| 1957 for (const std::pair<NaClBcIndexSize_t, Ice::Operand *> Elmt : LocalOperands) | |
|
Jim Stichnoth
2015/08/08 16:14:48
I think this calls for auto:
for (auto &Elmt :
Karl
2015/08/10 18:13:09
Good point. I didn't put the auto in because I did
| |
| 1958 if (Elmt.first >= NextLocalInstIndex) | |
| 1959 UndefinedFwdRefs.push_back(Elmt.first); | |
| 1960 std::sort(UndefinedFwdRefs.begin(), UndefinedFwdRefs.end()); | |
| 1961 for (const NaClBcIndexSize_t Index : UndefinedFwdRefs) { | |
| 1962 std::string Buffer; | |
| 1963 raw_string_ostream StrBuf(Buffer); | |
| 1964 StrBuf << "Instruction forward reference not defined: " << Index; | |
| 1965 Error(StrBuf.str()); | |
| 1966 } | |
| 1967 return false; | |
| 1968 } | |
| 1969 | |
| 1961 bool FunctionParser::verifyAndRenameBasicBlocks() { | 1970 bool FunctionParser::verifyAndRenameBasicBlocks() { |
| 1962 const size_t NumFoundBbs = BbMap.size(); | 1971 const size_t NumFoundBbs = BbMap.size(); |
| 1963 // Verify number of basic blocks found match amount specified in function. | 1972 // Verify number of basic blocks found match amount specified in function. |
| 1964 if (NumFoundBbs != SpecifiedNumBbs) { | 1973 if (NumFoundBbs != SpecifiedNumBbs) { |
| 1965 std::string Buffer; | 1974 std::string Buffer; |
| 1966 raw_string_ostream StrBuf(Buffer); | 1975 raw_string_ostream StrBuf(Buffer); |
| 1967 StrBuf << "Function specified " << SpecifiedNumBbs | 1976 StrBuf << "Function specified " << SpecifiedNumBbs |
| 1968 << "basic blocks. Found: " << NumFoundBbs; | 1977 << "basic blocks. Found: " << NumFoundBbs; |
| 1969 Error(StrBuf.str()); | 1978 Error(StrBuf.str()); |
| 1970 return false; | 1979 return false; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 2000 // Check if the last instruction in the function was terminating. | 2009 // Check if the last instruction in the function was terminating. |
| 2001 if (!InstIsTerminating) { | 2010 if (!InstIsTerminating) { |
| 2002 Error("Last instruction in function not terminator"); | 2011 Error("Last instruction in function not terminator"); |
| 2003 if (isIRGenerationDisabled()) | 2012 if (isIRGenerationDisabled()) |
| 2004 return; | 2013 return; |
| 2005 // Recover by inserting an unreachable instruction. | 2014 // Recover by inserting an unreachable instruction. |
| 2006 CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get())); | 2015 CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get())); |
| 2007 } | 2016 } |
| 2008 if (isIRGenerationDisabled()) | 2017 if (isIRGenerationDisabled()) |
| 2009 return; | 2018 return; |
| 2019 if (!verifyAllForwardRefsDefined()) | |
| 2020 return; | |
| 2010 if (!verifyAndRenameBasicBlocks()) | 2021 if (!verifyAndRenameBasicBlocks()) |
| 2011 return; | 2022 return; |
| 2012 // Before translating, check for blocks without instructions, and | 2023 // Before translating, check for blocks without instructions, and |
| 2013 // insert unreachable. This shouldn't happen, but be safe. | 2024 // insert unreachable. This shouldn't happen, but be safe. |
| 2014 size_t Index = 0; | 2025 size_t Index = 0; |
| 2015 for (Ice::CfgNode *Node : Func->getNodes()) { | 2026 for (Ice::CfgNode *Node : Func->getNodes()) { |
| 2016 if (Node->getInsts().empty()) { | 2027 if (Node->getInsts().empty()) { |
| 2017 std::string Buffer; | 2028 std::string Buffer; |
| 2018 raw_string_ostream StrBuf(Buffer); | 2029 raw_string_ostream StrBuf(Buffer); |
| 2019 StrBuf << "Basic block " << Index << " contains no instructions"; | 2030 StrBuf << "Basic block " << Index << " contains no instructions"; |
| (...skipping 1120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3140 } | 3151 } |
| 3141 if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) { | 3152 if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) { |
| 3142 ErrStream | 3153 ErrStream |
| 3143 << IRFilename | 3154 << IRFilename |
| 3144 << ": Bitcode stream should be a multiple of 4 bytes in length.\n"; | 3155 << ": Bitcode stream should be a multiple of 4 bytes in length.\n"; |
| 3145 llvm::report_fatal_error("Bitcode stream should be a multiple of 4 bytes"); | 3156 llvm::report_fatal_error("Bitcode stream should be a multiple of 4 bytes"); |
| 3146 } | 3157 } |
| 3147 } | 3158 } |
| 3148 | 3159 |
| 3149 } // end of namespace Ice | 3160 } // end of namespace Ice |
| OLD | NEW |