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

Side by Side Diff: src/PNaClTranslator.cpp

Issue 1297433002: Change tracking of basic blocks (within function) to use a vector. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix nits. 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
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 1233 matching lines...) Expand 10 before | Expand all | Expand 10 after
1244 if (isIRGenerationDisabled()) { 1244 if (isIRGenerationDisabled()) {
1245 CurrentNode = nullptr; 1245 CurrentNode = nullptr;
1246 for (Ice::Type ArgType : Signature.getArgList()) { 1246 for (Ice::Type ArgType : Signature.getArgList()) {
1247 (void)ArgType; 1247 (void)ArgType;
1248 setNextLocalInstIndex(nullptr); 1248 setNextLocalInstIndex(nullptr);
1249 } 1249 }
1250 } else { 1250 } else {
1251 Func->setFunctionName(FuncDecl->getName()); 1251 Func->setFunctionName(FuncDecl->getName());
1252 Func->setReturnType(Signature.getReturnType()); 1252 Func->setReturnType(Signature.getReturnType());
1253 Func->setInternal(FuncDecl->getLinkage() == GlobalValue::InternalLinkage); 1253 Func->setInternal(FuncDecl->getLinkage() == GlobalValue::InternalLinkage);
1254 constexpr NaClBcIndexSize_t EntryBlock = 0; 1254 CurrentNode = installNextBasicBlock();
1255 CurrentNode = getBasicBlock(EntryBlock);
1256 Func->setEntryNode(CurrentNode); 1255 Func->setEntryNode(CurrentNode);
1257 for (Ice::Type ArgType : Signature.getArgList()) { 1256 for (Ice::Type ArgType : Signature.getArgList()) {
1258 Func->addArg(getNextInstVar(ArgType)); 1257 Func->addArg(getNextInstVar(ArgType));
1259 } 1258 }
1260 } 1259 }
1261 bool ParserResult = ParseThisBlock(); 1260 bool ParserResult = ParseThisBlock();
1262 1261
1263 // Temporarily end per-function timing, which will be resumed by 1262 // Temporarily end per-function timing, which will be resumed by
1264 // the translator function. This is because translation may be 1263 // the translator function. This is because translation may be
1265 // done asynchronously in a separate thread. 1264 // done asynchronously in a separate thread.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1307 if (isIRGenerationDisabled()) 1306 if (isIRGenerationDisabled())
1308 return nullptr; 1307 return nullptr;
1309 std::string Buffer; 1308 std::string Buffer;
1310 raw_string_ostream StrBuf(Buffer); 1309 raw_string_ostream StrBuf(Buffer);
1311 StrBuf << "Value index " << Index << " not defined!"; 1310 StrBuf << "Value index " << Index << " not defined!";
1312 Fatal(StrBuf.str()); 1311 Fatal(StrBuf.str());
1313 } 1312 }
1314 return Op; 1313 return Op;
1315 } 1314 }
1316 1315
1317 // Returns the Index-th basic block in the list of basic blocks.
1318 Ice::CfgNode *getBasicBlock(NaClBcIndexSize_t Index) {
1319 assert(!isIRGenerationDisabled());
1320 Ice::CfgNode *&Node = BbMap[Index];
1321 if (Node == nullptr)
1322 Node = Func->makeNode();
1323 return Node;
1324 }
1325
1326 private: 1316 private:
1327 typedef std::unordered_map<NaClBcIndexSize_t, Ice::Operand *> OperandMap; 1317 typedef std::unordered_map<NaClBcIndexSize_t, Ice::Operand *> OperandMap;
1328 typedef std::unordered_map<NaClBcIndexSize_t, Ice::CfgNode *> CfgNodeMap; 1318 typedef std::vector<Ice::CfgNode *> BlockNodesType;
1329 1319
1330 Ice::TimerMarker Timer; 1320 Ice::TimerMarker Timer;
1321 // The number of words in the bitstream defining the function block.
1322 uint64_t NumBytesDefiningFunction = 0;
1331 // The corresponding ICE function defined by the function block. 1323 // The corresponding ICE function defined by the function block.
1332 std::unique_ptr<Ice::Cfg> Func; 1324 std::unique_ptr<Ice::Cfg> Func;
1333 // The specified number of basic blocks in the bitcode file.
1334 NaClBcIndexSize_t SpecifiedNumBbs = 0;
1335 // The index to the current basic block being built. 1325 // The index to the current basic block being built.
1336 NaClBcIndexSize_t CurrentBbIndex = 0; 1326 NaClBcIndexSize_t CurrentBbIndex = 0;
1327 // The number of basic blocks declared for the function block.
1328 NaClBcIndexSize_t DeclaredNumberBbs = 0;
1337 // The basic block being built. 1329 // The basic block being built.
1338 Ice::CfgNode *CurrentNode = nullptr; 1330 Ice::CfgNode *CurrentNode = nullptr;
1339 // Map from basic block id (as defined in the bitcode file) to 1331 // Vector of basic blocks. Used instead of indexing Func->getNodes() for
1340 // the corresponding basic block that implements it. 1332 // faster access (constant vs linear).
Jim Stichnoth 2015/08/13 23:16:25 This comment is wrong -- Func->getNodes() returns
Karl 2015/08/14 19:18:21 Your right. I was confusing this with LLVM code. R
1341 CfgNodeMap BbMap; 1333 BlockNodesType BlockNodes;
1342 // The ID for the function. 1334 // The ID for the function.
1343 NaClBcIndexSize_t FcnId; 1335 NaClBcIndexSize_t FcnId;
1344 // The corresponding function declaration. 1336 // The corresponding function declaration.
1345 Ice::FunctionDeclaration *FuncDecl; 1337 Ice::FunctionDeclaration *FuncDecl;
1346 // Holds the dividing point between local and global absolute value indices. 1338 // Holds the dividing point between local and global absolute value indices.
1347 size_t CachedNumGlobalValueIDs; 1339 size_t CachedNumGlobalValueIDs;
1348 // Holds operands local to the function block, based on indices 1340 // Holds operands local to the function block, based on indices
1349 // defined in the bitcode file. 1341 // defined in the bitcode file.
1350 OperandMap LocalOperands; 1342 OperandMap LocalOperands;
1351 // Holds the index within LocalOperands corresponding to the next 1343 // Holds the index within LocalOperands corresponding to the next
(...skipping 20 matching lines...) Expand all
1372 << ". Found: 2**" << (AlignPower - 1); 1364 << ". Found: 2**" << (AlignPower - 1);
1373 Error(StrBuf.str()); 1365 Error(StrBuf.str());
1374 // Error recover with value that is always acceptable. 1366 // Error recover with value that is always acceptable.
1375 Alignment = 1; 1367 Alignment = 1;
1376 } 1368 }
1377 1369
1378 bool ParseBlock(unsigned BlockID) override; 1370 bool ParseBlock(unsigned BlockID) override;
1379 1371
1380 void ProcessRecord() override; 1372 void ProcessRecord() override;
1381 1373
1374 void EnterBlock(unsigned NumWords) final {
1375 // Note: Bitstream defines words as 32-bit values.
1376 NumBytesDefiningFunction = NumWords * 4;
1377 }
1378
1382 void ExitBlock() override; 1379 void ExitBlock() override;
1383 1380
1384 bool verifyAndRenameBasicBlocks(); 1381 bool verifyAllForwardRefsDefined();
1385 1382
1386 bool verifyAllForwardRefsDefined(); 1383 // Creates and appends a new basic block to the list of basic blocks.
1384 Ice::CfgNode *installNextBasicBlock() {
1385 assert(!isIRGenerationDisabled());
1386 Ice::CfgNode *Node = Func->makeNode();
1387 BlockNodes.push_back(Node);
1388 return Node;
1389 }
1390
1391 // Returns the Index-th basic block in the list of basic blocks.
1392 Ice::CfgNode *getBasicBlock(NaClBcIndexSize_t Index) {
1393 assert(!isIRGenerationDisabled());
1394 if (Index >= BlockNodes.size()) {
1395 std::string Buffer;
1396 raw_string_ostream StrBuf(Buffer);
1397 StrBuf << "Reference to basic block " << Index
1398 << " not found. Must be less than " << BlockNodes.size();
1399 Error(StrBuf.str());
1400 // TODO(kschimpf) Remove error recovery once implementation complete.
Jim Stichnoth 2015/08/13 23:16:25 Remove this TODO like in the previous CL?
Karl 2015/08/14 19:18:21 Done.
1401 Index = 0;
1402 }
1403 return BlockNodes[Index];
1404 }
1387 1405
1388 // Returns the Index-th basic block in the list of basic blocks. 1406 // Returns the Index-th basic block in the list of basic blocks.
1389 // Assumes Index corresponds to a branch instruction. Hence, if 1407 // Assumes Index corresponds to a branch instruction. Hence, if
1390 // the branch references the entry block, it also generates a 1408 // the branch references the entry block, it also generates a
1391 // corresponding error. 1409 // corresponding error.
1392 Ice::CfgNode *getBranchBasicBlock(NaClBcIndexSize_t Index) { 1410 Ice::CfgNode *getBranchBasicBlock(NaClBcIndexSize_t Index) {
1393 assert(!isIRGenerationDisabled()); 1411 assert(!isIRGenerationDisabled());
1394 if (Index == 0) { 1412 if (Index == 0) {
1395 Error("Branch to entry block not allowed"); 1413 Error("Branch to entry block not allowed");
1396 } 1414 }
(...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after
1989 std::sort(UndefinedFwdRefs.begin(), UndefinedFwdRefs.end()); 2007 std::sort(UndefinedFwdRefs.begin(), UndefinedFwdRefs.end());
1990 for (const NaClBcIndexSize_t Index : UndefinedFwdRefs) { 2008 for (const NaClBcIndexSize_t Index : UndefinedFwdRefs) {
1991 std::string Buffer; 2009 std::string Buffer;
1992 raw_string_ostream StrBuf(Buffer); 2010 raw_string_ostream StrBuf(Buffer);
1993 StrBuf << "Instruction forward reference not defined: " << Index; 2011 StrBuf << "Instruction forward reference not defined: " << Index;
1994 Error(StrBuf.str()); 2012 Error(StrBuf.str());
1995 } 2013 }
1996 return false; 2014 return false;
1997 } 2015 }
1998 2016
1999 bool FunctionParser::verifyAndRenameBasicBlocks() {
2000 const size_t NumFoundBbs = BbMap.size();
2001 // Verify number of basic blocks found match amount specified in function.
2002 if (NumFoundBbs != SpecifiedNumBbs) {
2003 std::string Buffer;
2004 raw_string_ostream StrBuf(Buffer);
2005 StrBuf << "Function specified " << SpecifiedNumBbs
2006 << "basic blocks. Found: " << NumFoundBbs;
2007 Error(StrBuf.str());
2008 return false;
2009 }
2010 // Verify size limit allowed for basic blocks.
2011 if (NumFoundBbs > NaClBcIndexSize_t_Max) {
2012 std::string Buffer;
2013 raw_string_ostream StrBuf(Buffer);
2014 StrBuf << "Functions can't define more than " << NaClBcIndexSize_t_Max
2015 << "basic blocks. Found: " << NumFoundBbs;
2016 Error(StrBuf.str());
2017 return false;
2018 }
2019 // Sort list of Bbs, verifying that no basic blocks are missing.
2020 Ice::NodeList SortedBbs;
2021 for (size_t i = 0; i < NumFoundBbs; ++i) {
2022 CfgNodeMap::iterator pos = BbMap.find(i);
2023 if (pos == BbMap.end()) {
2024 std::string Buffer;
2025 raw_string_ostream StrBuf(Buffer);
2026 StrBuf << "Can't find definition for basic block " << i << ".";
2027 Error(StrBuf.str());
2028 return false;
2029 }
2030 SortedBbs.push_back(pos->second);
2031 }
2032 // Install sorted basic blocks.
2033 Func->swapNodes(SortedBbs);
2034 return true;
2035 }
2036
2037 void FunctionParser::ExitBlock() { 2017 void FunctionParser::ExitBlock() {
2038 // Check if the last instruction in the function was terminating. 2018 // Check if the last instruction in the function was terminating.
2039 if (!InstIsTerminating) { 2019 if (!InstIsTerminating) {
2040 Error("Last instruction in function not terminator"); 2020 Error("Last instruction in function not terminator");
2041 if (isIRGenerationDisabled()) 2021 if (isIRGenerationDisabled())
2042 return; 2022 return;
2043 // Recover by inserting an unreachable instruction. 2023 // Recover by inserting an unreachable instruction.
2044 CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get())); 2024 CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get()));
2045 } 2025 }
2026 ++CurrentBbIndex;
2027 if (CurrentBbIndex != DeclaredNumberBbs) {
2028 std::string Buffer;
2029 raw_string_ostream StrBuf(Buffer);
2030 StrBuf << "Function declared " << DeclaredNumberBbs
2031 << " basic blocks, but defined " << CurrentBbIndex << ".";
2032 Error(StrBuf.str());
2033 }
2046 if (isIRGenerationDisabled()) 2034 if (isIRGenerationDisabled())
2047 return; 2035 return;
2048 if (!verifyAllForwardRefsDefined()) 2036 if (!verifyAllForwardRefsDefined())
2049 return; 2037 return;
2050 if (!verifyAndRenameBasicBlocks())
2051 return;
2052 // Before translating, check for blocks without instructions, and 2038 // Before translating, check for blocks without instructions, and
2053 // insert unreachable. This shouldn't happen, but be safe. 2039 // insert unreachable. This shouldn't happen, but be safe.
2054 size_t Index = 0; 2040 size_t Index = 0;
2055 for (Ice::CfgNode *Node : Func->getNodes()) { 2041 for (Ice::CfgNode *Node : Func->getNodes()) {
2056 if (Node->getInsts().empty()) { 2042 if (Node->getInsts().empty()) {
2057 std::string Buffer; 2043 std::string Buffer;
2058 raw_string_ostream StrBuf(Buffer); 2044 raw_string_ostream StrBuf(Buffer);
2059 StrBuf << "Basic block " << Index << " contains no instructions"; 2045 StrBuf << "Basic block " << Index << " contains no instructions";
2060 Error(StrBuf.str()); 2046 Error(StrBuf.str());
2061 Node->appendInst(Ice::InstUnreachable::create(Func.get())); 2047 Node->appendInst(Ice::InstUnreachable::create(Func.get()));
(...skipping 13 matching lines...) Expand all
2075 } 2061 }
2076 2062
2077 void FunctionParser::ProcessRecord() { 2063 void FunctionParser::ProcessRecord() {
2078 // Note: To better separate parse/IR generation times, when IR generation 2064 // Note: To better separate parse/IR generation times, when IR generation
2079 // is disabled we do the following: 2065 // is disabled we do the following:
2080 // 1) Delay exiting until after we extract operands. 2066 // 1) Delay exiting until after we extract operands.
2081 // 2) return before we access operands, since all operands will be a nullptr. 2067 // 2) return before we access operands, since all operands will be a nullptr.
2082 const NaClBitcodeRecord::RecordVector &Values = Record.GetValues(); 2068 const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
2083 if (InstIsTerminating) { 2069 if (InstIsTerminating) {
2084 InstIsTerminating = false; 2070 InstIsTerminating = false;
2071 ++CurrentBbIndex;
2085 if (!isIRGenerationDisabled()) 2072 if (!isIRGenerationDisabled())
2086 CurrentNode = getBasicBlock(++CurrentBbIndex); 2073 CurrentNode = getBasicBlock(CurrentBbIndex);
2087 } 2074 }
2088 // The base index for relative indexing. 2075 // The base index for relative indexing.
2089 NaClBcIndexSize_t BaseIndex = getNextInstIndex(); 2076 NaClBcIndexSize_t BaseIndex = getNextInstIndex();
2090 switch (Record.GetCode()) { 2077 switch (Record.GetCode()) {
2091 case naclbitc::FUNC_CODE_DECLAREBLOCKS: { 2078 case naclbitc::FUNC_CODE_DECLAREBLOCKS: {
2092 // DECLAREBLOCKS: [n] 2079 // DECLAREBLOCKS: [n]
2093 if (!isValidRecordSize(1, "count")) 2080 if (!isValidRecordSize(1, "count"))
2094 return; 2081 return;
2095 uint64_t NumBbsRaw = Values[0]; 2082 if (DeclaredNumberBbs > 0) {
2096 if (NumBbsRaw == 0) {
2097 Error("Functions must contain at least one basic block.");
2098 NumBbsRaw = 1;
2099 } else if (NumBbsRaw > NaClBcIndexSize_t_Max) {
2100 std::string Buffer;
2101 raw_string_ostream StrBuf(Buffer);
2102 StrBuf << "To many basic blocks specified: " << NumBbsRaw;
2103 Error(StrBuf.str());
2104 NumBbsRaw = NaClBcIndexSize_t_Max;
2105 }
2106 if (isIRGenerationDisabled())
2107 return;
2108 if (SpecifiedNumBbs != 0) {
2109 Error("Duplicate function block count record"); 2083 Error("Duplicate function block count record");
2110 return; 2084 return;
2111 } 2085 }
2112 SpecifiedNumBbs = NumBbsRaw; 2086
2087 uint64_t NumBbs = Values[0];
2088
2089 // Check for bad large sizes, since they can make ridiculous memory
2090 // requests and hang the user for large amounts of time. Note: We know
2091 // that each basic block must have a terminator instruction, and each
2092 // instruction is minimally defined by a two-bit abreviation.
2093 uint64_t MaxBbs = NumBytesDefiningFunction * (CHAR_BIT >> 1);
2094 if (NumBbs > MaxBbs) {
2095 std::string Buffer;
2096 raw_string_ostream StrBuf(Buffer);
2097 StrBuf << "Function defines " << NumBbs
2098 << " basic blocks, which is too big for a function containing "
2099 << NumBytesDefiningFunction << " bytes";
2100 Error(StrBuf.str());
2101 NumBbs = MaxBbs;
2102 }
2103
2104 if (NumBbs == 0) {
2105 Error("Functions must contain at least one basic block.");
2106 NumBbs = 1;
2107 }
2108
2109 DeclaredNumberBbs = NumBbs;
2110 if (isIRGenerationDisabled())
2111 return;
2112 // Install the basic blocks, skipping bb0 which was created in the
2113 // constructor.
2114 BlockNodes.reserve(NumBbs);
2115 for (size_t i = 1; i < NumBbs; ++i)
2116 installNextBasicBlock();
2113 return; 2117 return;
2114 } 2118 }
2115 case naclbitc::FUNC_CODE_INST_BINOP: { 2119 case naclbitc::FUNC_CODE_INST_BINOP: {
2116 // BINOP: [opval, opval, opcode] 2120 // BINOP: [opval, opval, opcode]
2117 if (!isValidRecordSize(3, "binop")) 2121 if (!isValidRecordSize(3, "binop"))
2118 return; 2122 return;
2119 Ice::Operand *Op1 = getRelativeOperand(Values[0], BaseIndex); 2123 Ice::Operand *Op1 = getRelativeOperand(Values[0], BaseIndex);
2120 Ice::Operand *Op2 = getRelativeOperand(Values[1], BaseIndex); 2124 Ice::Operand *Op2 = getRelativeOperand(Values[1], BaseIndex);
2121 if (isIRGenerationDisabled()) { 2125 if (isIRGenerationDisabled()) {
2122 assert(Op1 == nullptr && Op2 == nullptr); 2126 assert(Op1 == nullptr && Op2 == nullptr);
(...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after
2926 reportUnableToAssign("variable", Index, Name); 2930 reportUnableToAssign("variable", Index, Name);
2927 } 2931 }
2928 } 2932 }
2929 2933
2930 void FunctionValuesymtabParser::setBbName(NaClBcIndexSize_t Index, 2934 void FunctionValuesymtabParser::setBbName(NaClBcIndexSize_t Index,
2931 StringType &Name) { 2935 StringType &Name) {
2932 if (!Ice::BuildDefs::dump()) 2936 if (!Ice::BuildDefs::dump())
2933 return; 2937 return;
2934 if (isIRGenerationDisabled()) 2938 if (isIRGenerationDisabled())
2935 return; 2939 return;
2936 Ice::CfgNode *Bb = getFunctionParser()->getBasicBlock(Index); 2940 if (Index >= getFunctionParser()->getFunc()->getNumNodes()) {
2941 reportUnableToAssign("block", Index, Name);
2942 return;
2943 }
2937 std::string Nm(Name.data(), Name.size()); 2944 std::string Nm(Name.data(), Name.size());
2938 Bb->setName(Nm); 2945 if (Ice::BuildDefs::dump())
2946 getFunctionParser()->getFunc()->getNodes()[Index]->setName(Nm);
2939 } 2947 }
2940 2948
2941 bool FunctionParser::ParseBlock(unsigned BlockID) { 2949 bool FunctionParser::ParseBlock(unsigned BlockID) {
2942 switch (BlockID) { 2950 switch (BlockID) {
2943 case naclbitc::CONSTANTS_BLOCK_ID: { 2951 case naclbitc::CONSTANTS_BLOCK_ID: {
2944 ConstantsParser Parser(BlockID, this); 2952 ConstantsParser Parser(BlockID, this);
2945 return Parser.ParseThisBlock(); 2953 return Parser.ParseThisBlock();
2946 } 2954 }
2947 case naclbitc::VALUE_SYMTAB_BLOCK_ID: { 2955 case naclbitc::VALUE_SYMTAB_BLOCK_ID: {
2948 if (PNaClAllowLocalSymbolTables) { 2956 if (PNaClAllowLocalSymbolTables) {
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
3174 } 3182 }
3175 if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) { 3183 if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) {
3176 ErrStream 3184 ErrStream
3177 << IRFilename 3185 << IRFilename
3178 << ": Bitcode stream should be a multiple of 4 bytes in length.\n"; 3186 << ": Bitcode stream should be a multiple of 4 bytes in length.\n";
3179 llvm::report_fatal_error("Bitcode stream should be a multiple of 4 bytes"); 3187 llvm::report_fatal_error("Bitcode stream should be a multiple of 4 bytes");
3180 } 3188 }
3181 } 3189 }
3182 3190
3183 } // end of namespace Ice 3191 } // end of namespace Ice
OLDNEW
« no previous file with comments | « no previous file | tests_lit/parse_errs/Inputs/bad-bb-size.tbc » ('j') | tests_lit/parse_errs/bad-bb-size.test » ('J')

Powered by Google App Engine
This is Rietveld 408576698