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 1233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |