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 |