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 18 matching lines...) Expand all Loading... | |
| 29 #pragma clang diagnostic ignored "-Wunused-parameter" | 29 #pragma clang diagnostic ignored "-Wunused-parameter" |
| 30 #include "llvm/ADT/SmallString.h" | 30 #include "llvm/ADT/SmallString.h" |
| 31 #include "llvm/Bitcode/NaCl/NaClBitcodeDecoders.h" | 31 #include "llvm/Bitcode/NaCl/NaClBitcodeDecoders.h" |
| 32 #include "llvm/Bitcode/NaCl/NaClBitcodeDefs.h" | 32 #include "llvm/Bitcode/NaCl/NaClBitcodeDefs.h" |
| 33 #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h" | 33 #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h" |
| 34 #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" | 34 #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" |
| 35 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" | 35 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" |
| 36 #include "llvm/Support/Format.h" | 36 #include "llvm/Support/Format.h" |
| 37 #include "llvm/Support/MemoryBuffer.h" | 37 #include "llvm/Support/MemoryBuffer.h" |
| 38 #include "llvm/Support/raw_ostream.h" | 38 #include "llvm/Support/raw_ostream.h" |
| 39 #include <unordered_map> | |
|
Jim Stichnoth
2015/08/06 19:41:21
Could you move this include into IceDefs.h, and re
Karl
2015/08/06 19:55:41
Done.
| |
| 39 #pragma clang diagnostic pop | 40 #pragma clang diagnostic pop |
| 40 | 41 |
| 41 namespace { | 42 namespace { |
| 42 using namespace llvm; | 43 using namespace llvm; |
| 43 | 44 |
| 44 // Models elements in the list of types defined in the types block. | 45 // Models elements in the list of types defined in the types block. |
| 45 // These elements can be undefined, a (simple) type, or a function type | 46 // These elements can be undefined, a (simple) type, or a function type |
| 46 // signature. Note that an extended type is undefined on construction. | 47 // signature. Note that an extended type is undefined on construction. |
| 47 // Use methods setAsSimpleType and setAsFuncSigType to define | 48 // Use methods setAsSimpleType and setAsFuncSigType to define |
| 48 // the extended type. | 49 // the extended type. |
| (...skipping 1159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1208 if (isIRGenerationDisabled()) { | 1209 if (isIRGenerationDisabled()) { |
| 1209 CurrentNode = nullptr; | 1210 CurrentNode = nullptr; |
| 1210 for (Ice::Type ArgType : Signature.getArgList()) { | 1211 for (Ice::Type ArgType : Signature.getArgList()) { |
| 1211 (void)ArgType; | 1212 (void)ArgType; |
| 1212 setNextLocalInstIndex(nullptr); | 1213 setNextLocalInstIndex(nullptr); |
| 1213 } | 1214 } |
| 1214 } else { | 1215 } else { |
| 1215 Func->setFunctionName(FuncDecl->getName()); | 1216 Func->setFunctionName(FuncDecl->getName()); |
| 1216 Func->setReturnType(Signature.getReturnType()); | 1217 Func->setReturnType(Signature.getReturnType()); |
| 1217 Func->setInternal(FuncDecl->getLinkage() == GlobalValue::InternalLinkage); | 1218 Func->setInternal(FuncDecl->getLinkage() == GlobalValue::InternalLinkage); |
| 1218 CurrentNode = installNextBasicBlock(); | 1219 constexpr NaClBcIndexSize_t EntryBlock = 0; |
| 1220 CurrentNode = getBasicBlock(EntryBlock); | |
| 1219 Func->setEntryNode(CurrentNode); | 1221 Func->setEntryNode(CurrentNode); |
| 1220 for (Ice::Type ArgType : Signature.getArgList()) { | 1222 for (Ice::Type ArgType : Signature.getArgList()) { |
| 1221 Func->addArg(getNextInstVar(ArgType)); | 1223 Func->addArg(getNextInstVar(ArgType)); |
| 1222 } | 1224 } |
| 1223 } | 1225 } |
| 1224 bool ParserResult = ParseThisBlock(); | 1226 bool ParserResult = ParseThisBlock(); |
| 1225 | 1227 |
| 1226 // Temporarily end per-function timing, which will be resumed by | 1228 // Temporarily end per-function timing, which will be resumed by |
| 1227 // the translator function. This is because translation may be | 1229 // the translator function. This is because translation may be |
| 1228 // done asynchronously in a separate thread. | 1230 // done asynchronously in a separate thread. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1276 if (isIRGenerationDisabled()) | 1278 if (isIRGenerationDisabled()) |
| 1277 return nullptr; | 1279 return nullptr; |
| 1278 std::string Buffer; | 1280 std::string Buffer; |
| 1279 raw_string_ostream StrBuf(Buffer); | 1281 raw_string_ostream StrBuf(Buffer); |
| 1280 StrBuf << "Value index " << Index << " not defined!"; | 1282 StrBuf << "Value index " << Index << " not defined!"; |
| 1281 Fatal(StrBuf.str()); | 1283 Fatal(StrBuf.str()); |
| 1282 } | 1284 } |
| 1283 return Op; | 1285 return Op; |
| 1284 } | 1286 } |
| 1285 | 1287 |
| 1288 // Returns the Index-th basic block in the list of basic blocks. | |
| 1289 Ice::CfgNode *getBasicBlock(NaClBcIndexSize_t Index) { | |
| 1290 assert(!isIRGenerationDisabled()); | |
| 1291 Ice::CfgNode *&Node = BbMap[Index]; | |
| 1292 if (Node == nullptr) | |
| 1293 Node = Func->makeNode(); | |
| 1294 return Node; | |
| 1295 } | |
| 1296 | |
| 1286 private: | 1297 private: |
| 1298 typedef std::unordered_map<NaClBcIndexSize_t, Ice::CfgNode *> CfgNodeMap; | |
| 1299 | |
| 1287 Ice::TimerMarker Timer; | 1300 Ice::TimerMarker Timer; |
| 1288 // The corresponding ICE function defined by the function block. | 1301 // The corresponding ICE function defined by the function block. |
| 1289 std::unique_ptr<Ice::Cfg> Func; | 1302 std::unique_ptr<Ice::Cfg> Func; |
| 1303 // The specified number of basic blocks in the bitcode file. | |
| 1304 NaClBcIndexSize_t SpecifiedNumBbs = 0; | |
| 1290 // The index to the current basic block being built. | 1305 // The index to the current basic block being built. |
| 1291 NaClBcIndexSize_t CurrentBbIndex = 0; | 1306 NaClBcIndexSize_t CurrentBbIndex = 0; |
| 1292 // The basic block being built. | 1307 // The basic block being built. |
| 1293 Ice::CfgNode *CurrentNode = nullptr; | 1308 Ice::CfgNode *CurrentNode = nullptr; |
| 1309 // Map from basic block id (as defined in the bitcode file) to | |
| 1310 // the corresponding basic block that implements it. | |
| 1311 CfgNodeMap BbMap; | |
| 1294 // The ID for the function. | 1312 // The ID for the function. |
| 1295 NaClBcIndexSize_t FcnId; | 1313 NaClBcIndexSize_t FcnId; |
| 1296 // The corresponding function declaration. | 1314 // The corresponding function declaration. |
| 1297 Ice::FunctionDeclaration *FuncDecl; | 1315 Ice::FunctionDeclaration *FuncDecl; |
| 1298 // Holds the dividing point between local and global absolute value indices. | 1316 // Holds the dividing point between local and global absolute value indices. |
| 1299 size_t CachedNumGlobalValueIDs; | 1317 size_t CachedNumGlobalValueIDs; |
| 1300 // Holds operands local to the function block, based on indices | 1318 // Holds operands local to the function block, based on indices |
| 1301 // defined in the bitcode file. | 1319 // defined in the bitcode file. |
| 1302 std::vector<Ice::Operand *> LocalOperands; | 1320 std::vector<Ice::Operand *> LocalOperands; |
| 1303 // Holds the index within LocalOperands corresponding to the next | 1321 // Holds the index within LocalOperands corresponding to the next |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1326 // Error recover with value that is always acceptable. | 1344 // Error recover with value that is always acceptable. |
| 1327 Alignment = 1; | 1345 Alignment = 1; |
| 1328 } | 1346 } |
| 1329 | 1347 |
| 1330 bool ParseBlock(unsigned BlockID) override; | 1348 bool ParseBlock(unsigned BlockID) override; |
| 1331 | 1349 |
| 1332 void ProcessRecord() override; | 1350 void ProcessRecord() override; |
| 1333 | 1351 |
| 1334 void ExitBlock() override; | 1352 void ExitBlock() override; |
| 1335 | 1353 |
| 1336 // Creates and appends a new basic block to the list of basic blocks. | 1354 bool verifyAndRenameBasicBlocks(); |
| 1337 Ice::CfgNode *installNextBasicBlock() { | |
| 1338 assert(!isIRGenerationDisabled()); | |
| 1339 return Func->makeNode(); | |
| 1340 } | |
| 1341 | |
| 1342 // Returns the Index-th basic block in the list of basic blocks. | |
| 1343 Ice::CfgNode *getBasicBlock(NaClBcIndexSize_t Index) { | |
| 1344 assert(!isIRGenerationDisabled()); | |
| 1345 const Ice::NodeList &Nodes = Func->getNodes(); | |
| 1346 if (Index >= Nodes.size()) { | |
| 1347 std::string Buffer; | |
| 1348 raw_string_ostream StrBuf(Buffer); | |
| 1349 StrBuf << "Reference to basic block " << Index | |
| 1350 << " not found. Must be less than " << Nodes.size(); | |
| 1351 Error(StrBuf.str()); | |
| 1352 // TODO(kschimpf) Remove error recovery once implementation complete. | |
| 1353 Index = 0; | |
| 1354 } | |
| 1355 return Nodes[Index]; | |
| 1356 } | |
| 1357 | 1355 |
| 1358 // Returns the Index-th basic block in the list of basic blocks. | 1356 // Returns the Index-th basic block in the list of basic blocks. |
| 1359 // Assumes Index corresponds to a branch instruction. Hence, if | 1357 // Assumes Index corresponds to a branch instruction. Hence, if |
| 1360 // the branch references the entry block, it also generates a | 1358 // the branch references the entry block, it also generates a |
| 1361 // corresponding error. | 1359 // corresponding error. |
| 1362 Ice::CfgNode *getBranchBasicBlock(NaClBcIndexSize_t Index) { | 1360 Ice::CfgNode *getBranchBasicBlock(NaClBcIndexSize_t Index) { |
| 1363 assert(!isIRGenerationDisabled()); | 1361 assert(!isIRGenerationDisabled()); |
| 1364 if (Index == 0) { | 1362 if (Index == 0) { |
| 1365 Error("Branch to entry block not allowed"); | 1363 Error("Branch to entry block not allowed"); |
| 1366 // TODO(kschimpf) Remove error recovery once implementation complete. | 1364 // TODO(kschimpf) Remove error recovery once implementation complete. |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1954 void appendErrorInstruction(Ice::Type Ty) { | 1952 void appendErrorInstruction(Ice::Type Ty) { |
| 1955 // Note: we don't worry about downstream translation errors because | 1953 // Note: we don't worry about downstream translation errors because |
| 1956 // the function will not be translated if any errors occur. | 1954 // the function will not be translated if any errors occur. |
| 1957 if (Ty == Ice::IceType_void) | 1955 if (Ty == Ice::IceType_void) |
| 1958 return; | 1956 return; |
| 1959 Ice::Variable *Var = getNextInstVar(Ty); | 1957 Ice::Variable *Var = getNextInstVar(Ty); |
| 1960 CurrentNode->appendInst(Ice::InstAssign::create(Func.get(), Var, Var)); | 1958 CurrentNode->appendInst(Ice::InstAssign::create(Func.get(), Var, Var)); |
| 1961 } | 1959 } |
| 1962 }; | 1960 }; |
| 1963 | 1961 |
| 1962 bool FunctionParser::verifyAndRenameBasicBlocks() { | |
| 1963 const size_t NumFoundBbs = BbMap.size(); | |
| 1964 // Verify number of basic blocks found match amount specified in function. | |
| 1965 if (NumFoundBbs != SpecifiedNumBbs) { | |
| 1966 std::string Buffer; | |
| 1967 raw_string_ostream StrBuf(Buffer); | |
| 1968 StrBuf << "Function specified " << SpecifiedNumBbs | |
| 1969 << "basic blocks. Found: " << NumFoundBbs; | |
| 1970 Error(StrBuf.str()); | |
| 1971 return false; | |
| 1972 } | |
| 1973 // Verify size limit allowed for basic blocks. | |
| 1974 if (NumFoundBbs > NaClBcIndexSize_t_Max) { | |
| 1975 std::string Buffer; | |
| 1976 raw_string_ostream StrBuf(Buffer); | |
| 1977 StrBuf << "Functions can't define more than " << NaClBcIndexSize_t_Max | |
| 1978 << "basic blocks. Found: " << NumFoundBbs; | |
| 1979 Error(StrBuf.str()); | |
| 1980 return false; | |
| 1981 } | |
| 1982 // Sort list of Bbs, verifying that no basic blocks are missing. | |
| 1983 Ice::NodeList SortedBbs; | |
| 1984 for (size_t i = 0; i < NumFoundBbs; ++i) { | |
| 1985 CfgNodeMap::iterator pos = BbMap.find(i); | |
| 1986 if (pos == BbMap.end()) { | |
| 1987 std::string Buffer; | |
| 1988 raw_string_ostream StrBuf(Buffer); | |
| 1989 StrBuf << "Can't find definition for basic block " << i << "."; | |
| 1990 Error(StrBuf.str()); | |
| 1991 return false; | |
| 1992 } | |
| 1993 SortedBbs.push_back(pos->second); | |
| 1994 } | |
| 1995 // Install sorted basic blocks. | |
| 1996 Func->swapNodes(SortedBbs); | |
| 1997 return true; | |
| 1998 } | |
| 1999 | |
| 1964 void FunctionParser::ExitBlock() { | 2000 void FunctionParser::ExitBlock() { |
| 1965 // Check if the last instruction in the function was terminating. | 2001 // Check if the last instruction in the function was terminating. |
| 1966 if (!InstIsTerminating) { | 2002 if (!InstIsTerminating) { |
| 1967 Error("Last instruction in function not terminator"); | 2003 Error("Last instruction in function not terminator"); |
| 1968 if (isIRGenerationDisabled()) | 2004 if (isIRGenerationDisabled()) |
| 1969 return; | 2005 return; |
| 1970 // Recover by inserting an unreachable instruction. | 2006 // Recover by inserting an unreachable instruction. |
| 1971 CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get())); | 2007 CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get())); |
| 1972 } | 2008 } |
| 1973 if (isIRGenerationDisabled()) | 2009 if (isIRGenerationDisabled()) |
| 1974 return; | 2010 return; |
| 2011 if (!verifyAndRenameBasicBlocks()) | |
| 2012 return; | |
| 1975 // Before translating, check for blocks without instructions, and | 2013 // Before translating, check for blocks without instructions, and |
| 1976 // insert unreachable. This shouldn't happen, but be safe. | 2014 // insert unreachable. This shouldn't happen, but be safe. |
| 1977 size_t Index = 0; | 2015 size_t Index = 0; |
| 1978 for (Ice::CfgNode *Node : Func->getNodes()) { | 2016 for (Ice::CfgNode *Node : Func->getNodes()) { |
| 1979 if (Node->getInsts().empty()) { | 2017 if (Node->getInsts().empty()) { |
| 1980 std::string Buffer; | 2018 std::string Buffer; |
| 1981 raw_string_ostream StrBuf(Buffer); | 2019 raw_string_ostream StrBuf(Buffer); |
| 1982 StrBuf << "Basic block " << Index << " contains no instructions"; | 2020 StrBuf << "Basic block " << Index << " contains no instructions"; |
| 1983 Error(StrBuf.str()); | 2021 Error(StrBuf.str()); |
| 1984 // TODO(kschimpf) Remove error recovery once implementation complete. | 2022 // TODO(kschimpf) Remove error recovery once implementation complete. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2023 NumBbsRaw = 1; | 2061 NumBbsRaw = 1; |
| 2024 } else if (NumBbsRaw > NaClBcIndexSize_t_Max) { | 2062 } else if (NumBbsRaw > NaClBcIndexSize_t_Max) { |
| 2025 std::string Buffer; | 2063 std::string Buffer; |
| 2026 raw_string_ostream StrBuf(Buffer); | 2064 raw_string_ostream StrBuf(Buffer); |
| 2027 StrBuf << "To many basic blocks specified: " << NumBbsRaw; | 2065 StrBuf << "To many basic blocks specified: " << NumBbsRaw; |
| 2028 Error(StrBuf.str()); | 2066 Error(StrBuf.str()); |
| 2029 NumBbsRaw = NaClBcIndexSize_t_Max; | 2067 NumBbsRaw = NaClBcIndexSize_t_Max; |
| 2030 } | 2068 } |
| 2031 if (isIRGenerationDisabled()) | 2069 if (isIRGenerationDisabled()) |
| 2032 return; | 2070 return; |
| 2033 if (Func->getNodes().size() != 1) { | 2071 if (SpecifiedNumBbs != 0) { |
| 2034 Error("Duplicate function block count record"); | 2072 Error("Duplicate function block count record"); |
| 2035 return; | 2073 return; |
| 2036 } | 2074 } |
| 2037 // Install the basic blocks, skipping bb0 which was created in the | 2075 SpecifiedNumBbs = NumBbsRaw; |
| 2038 // constructor. | |
| 2039 for (size_t i = 1, NumBbs = NumBbsRaw; i < NumBbs; ++i) | |
| 2040 installNextBasicBlock(); | |
| 2041 return; | 2076 return; |
| 2042 } | 2077 } |
| 2043 case naclbitc::FUNC_CODE_INST_BINOP: { | 2078 case naclbitc::FUNC_CODE_INST_BINOP: { |
| 2044 // BINOP: [opval, opval, opcode] | 2079 // BINOP: [opval, opval, opcode] |
| 2045 if (!isValidRecordSize(3, "binop")) | 2080 if (!isValidRecordSize(3, "binop")) |
| 2046 return; | 2081 return; |
| 2047 Ice::Operand *Op1 = getRelativeOperand(Values[0], BaseIndex); | 2082 Ice::Operand *Op1 = getRelativeOperand(Values[0], BaseIndex); |
| 2048 Ice::Operand *Op2 = getRelativeOperand(Values[1], BaseIndex); | 2083 Ice::Operand *Op2 = getRelativeOperand(Values[1], BaseIndex); |
| 2049 if (isIRGenerationDisabled()) { | 2084 if (isIRGenerationDisabled()) { |
| 2050 assert(Op1 == nullptr && Op2 == nullptr); | 2085 assert(Op1 == nullptr && Op2 == nullptr); |
| (...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2854 std::string Nm(Name.data(), Name.size()); | 2889 std::string Nm(Name.data(), Name.size()); |
| 2855 V->setName(getFunctionParser()->getFunc(), Nm); | 2890 V->setName(getFunctionParser()->getFunc(), Nm); |
| 2856 } | 2891 } |
| 2857 } else { | 2892 } else { |
| 2858 reportUnableToAssign("variable", Index, Name); | 2893 reportUnableToAssign("variable", Index, Name); |
| 2859 } | 2894 } |
| 2860 } | 2895 } |
| 2861 | 2896 |
| 2862 void FunctionValuesymtabParser::setBbName(NaClBcIndexSize_t Index, | 2897 void FunctionValuesymtabParser::setBbName(NaClBcIndexSize_t Index, |
| 2863 StringType &Name) { | 2898 StringType &Name) { |
| 2864 if (isIRGenerationDisabled()) | 2899 if (isIRGenerationDisabled() || !Ice::BuildDefs::dump()) |
|
Jim Stichnoth
2015/08/06 19:41:21
Test for BuildDefs::dump() very first, even before
Karl
2015/08/06 19:55:41
Done.
| |
| 2865 return; | 2900 return; |
| 2866 if (Index >= getFunctionParser()->getFunc()->getNumNodes()) { | 2901 Ice::CfgNode *Bb = getFunctionParser()->getBasicBlock(Index); |
| 2867 reportUnableToAssign("block", Index, Name); | |
| 2868 return; | |
| 2869 } | |
| 2870 std::string Nm(Name.data(), Name.size()); | 2902 std::string Nm(Name.data(), Name.size()); |
| 2871 if (Ice::BuildDefs::dump()) | 2903 Bb->setName(Nm); |
| 2872 getFunctionParser()->getFunc()->getNodes()[Index]->setName(Nm); | |
| 2873 } | 2904 } |
| 2874 | 2905 |
| 2875 bool FunctionParser::ParseBlock(unsigned BlockID) { | 2906 bool FunctionParser::ParseBlock(unsigned BlockID) { |
| 2876 switch (BlockID) { | 2907 switch (BlockID) { |
| 2877 case naclbitc::CONSTANTS_BLOCK_ID: { | 2908 case naclbitc::CONSTANTS_BLOCK_ID: { |
| 2878 ConstantsParser Parser(BlockID, this); | 2909 ConstantsParser Parser(BlockID, this); |
| 2879 return Parser.ParseThisBlock(); | 2910 return Parser.ParseThisBlock(); |
| 2880 } | 2911 } |
| 2881 case naclbitc::VALUE_SYMTAB_BLOCK_ID: { | 2912 case naclbitc::VALUE_SYMTAB_BLOCK_ID: { |
| 2882 if (PNaClAllowLocalSymbolTables) { | 2913 if (PNaClAllowLocalSymbolTables) { |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3108 } | 3139 } |
| 3109 if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) { | 3140 if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) { |
| 3110 ErrStream | 3141 ErrStream |
| 3111 << IRFilename | 3142 << IRFilename |
| 3112 << ": Bitcode stream should be a multiple of 4 bytes in length.\n"; | 3143 << ": Bitcode stream should be a multiple of 4 bytes in length.\n"; |
| 3113 llvm::report_fatal_error("Bitcode stream should be a multiple of 4 bytes"); | 3144 llvm::report_fatal_error("Bitcode stream should be a multiple of 4 bytes"); |
| 3114 } | 3145 } |
| 3115 } | 3146 } |
| 3116 | 3147 |
| 3117 } // end of namespace Ice | 3148 } // end of namespace Ice |
| OLD | NEW |