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 // This file implements the PNaCl bitcode file to Ice, to machine code | 10 // This file implements the PNaCl bitcode file to Ice, to machine code |
11 // translator. | 11 // translator. |
12 // | 12 // |
13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
14 | 14 |
15 #include "PNaClTranslator.h" | 15 #include "PNaClTranslator.h" |
16 #include "IceCfg.h" | 16 #include "IceCfg.h" |
17 #include "IceCfgNode.h" | 17 #include "IceCfgNode.h" |
18 #include "IceClFlags.h" | 18 #include "IceClFlags.h" |
19 #include "IceDefs.h" | 19 #include "IceDefs.h" |
20 #include "IceInst.h" | 20 #include "IceInst.h" |
21 #include "IceOperand.h" | 21 #include "IceOperand.h" |
22 #include "IceTypeConverter.h" | 22 #include "IceTypeConverter.h" |
23 #include "llvm/Analysis/NaCl/PNaClABIProps.h" | |
23 #include "llvm/Bitcode/NaCl/NaClBitcodeDecoders.h" | 24 #include "llvm/Bitcode/NaCl/NaClBitcodeDecoders.h" |
24 #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h" | 25 #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h" |
25 #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" | 26 #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" |
26 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" | 27 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" |
27 #include "llvm/IR/Constants.h" | 28 #include "llvm/IR/Constants.h" |
29 #include "llvm/IR/DataLayout.h" | |
28 #include "llvm/IR/LLVMContext.h" | 30 #include "llvm/IR/LLVMContext.h" |
29 #include "llvm/IR/Module.h" | 31 #include "llvm/IR/Module.h" |
30 #include "llvm/Support/Format.h" | 32 #include "llvm/Support/Format.h" |
31 #include "llvm/Support/MemoryBuffer.h" | 33 #include "llvm/Support/MemoryBuffer.h" |
32 #include "llvm/Support/raw_ostream.h" | 34 #include "llvm/Support/raw_ostream.h" |
33 #include "llvm/Support/ValueHandle.h" | 35 #include "llvm/Support/ValueHandle.h" |
34 | 36 |
35 #include <vector> | 37 #include <vector> |
36 #include <cassert> | 38 #include <cassert> |
37 | 39 |
(...skipping 10 matching lines...) Expand all Loading... | |
48 // Top-level class to read PNaCl bitcode files, and translate to ICE. | 50 // Top-level class to read PNaCl bitcode files, and translate to ICE. |
49 class TopLevelParser : public NaClBitcodeParser { | 51 class TopLevelParser : public NaClBitcodeParser { |
50 TopLevelParser(const TopLevelParser &) LLVM_DELETED_FUNCTION; | 52 TopLevelParser(const TopLevelParser &) LLVM_DELETED_FUNCTION; |
51 TopLevelParser &operator=(const TopLevelParser &) LLVM_DELETED_FUNCTION; | 53 TopLevelParser &operator=(const TopLevelParser &) LLVM_DELETED_FUNCTION; |
52 | 54 |
53 public: | 55 public: |
54 TopLevelParser(Ice::Translator &Translator, const std::string &InputName, | 56 TopLevelParser(Ice::Translator &Translator, const std::string &InputName, |
55 NaClBitcodeHeader &Header, NaClBitstreamCursor &Cursor, | 57 NaClBitcodeHeader &Header, NaClBitstreamCursor &Cursor, |
56 bool &ErrorStatus) | 58 bool &ErrorStatus) |
57 : NaClBitcodeParser(Cursor), Translator(Translator), | 59 : NaClBitcodeParser(Cursor), Translator(Translator), |
58 Mod(new Module(InputName, getGlobalContext())), Header(Header), | 60 Mod(new Module(InputName, getGlobalContext())), DL(PNaClDataLayout), |
59 TypeConverter(getLLVMContext()), ErrorStatus(ErrorStatus), NumErrors(0), | 61 Header(Header), TypeConverter(getLLVMContext()), |
60 NumFunctionIds(0), NumFunctionBlocks(0), | 62 ErrorStatus(ErrorStatus), NumErrors(0), NumFunctionIds(0), |
63 NumFunctionBlocks(0), | |
61 GlobalVarPlaceHolderType(convertToLLVMType(Ice::IceType_i8)) { | 64 GlobalVarPlaceHolderType(convertToLLVMType(Ice::IceType_i8)) { |
62 Mod->setDataLayout(PNaClDataLayout); | 65 Mod->setDataLayout(PNaClDataLayout); |
63 } | 66 } |
64 | 67 |
65 virtual ~TopLevelParser() {} | 68 virtual ~TopLevelParser() {} |
66 LLVM_OVERRIDE; | 69 LLVM_OVERRIDE; |
67 | 70 |
68 Ice::Translator &getTranslator() { return Translator; } | 71 Ice::Translator &getTranslator() { return Translator; } |
69 | 72 |
70 // Generates error with given Message. Always returns true. | 73 // Generates error with given Message. Always returns true. |
71 virtual bool Error(const std::string &Message) LLVM_OVERRIDE { | 74 virtual bool Error(const std::string &Message) LLVM_OVERRIDE { |
72 ErrorStatus = true; | 75 ErrorStatus = true; |
73 ++NumErrors; | 76 ++NumErrors; |
74 NaClBitcodeParser::Error(Message); | 77 NaClBitcodeParser::Error(Message); |
75 if (!AllowErrorRecovery) | 78 if (!AllowErrorRecovery) |
76 report_fatal_error("Unable to continue"); | 79 report_fatal_error("Unable to continue"); |
77 return true; | 80 return true; |
78 } | 81 } |
79 | 82 |
80 /// Returns the number of errors found while parsing the bitcode | 83 /// Returns the number of errors found while parsing the bitcode |
81 /// file. | 84 /// file. |
82 unsigned getNumErrors() const { return NumErrors; } | 85 unsigned getNumErrors() const { return NumErrors; } |
83 | 86 |
84 /// Returns the LLVM module associated with the translation. | 87 /// Returns the LLVM module associated with the translation. |
85 Module *getModule() const { return Mod.get(); } | 88 Module *getModule() const { return Mod.get(); } |
86 | 89 |
90 const DataLayout &getDataLayout() const { return DL; } | |
91 | |
87 /// Returns the number of bytes in the bitcode header. | 92 /// Returns the number of bytes in the bitcode header. |
88 size_t getHeaderSize() const { return Header.getHeaderSize(); } | 93 size_t getHeaderSize() const { return Header.getHeaderSize(); } |
89 | 94 |
90 /// Returns the llvm context to use. | 95 /// Returns the llvm context to use. |
91 LLVMContext &getLLVMContext() const { return Mod->getContext(); } | 96 LLVMContext &getLLVMContext() const { return Mod->getContext(); } |
92 | 97 |
93 /// Changes the size of the type list to the given size. | 98 /// Changes the size of the type list to the given size. |
94 void resizeTypeIDValues(unsigned NewSize) { TypeIDValues.resize(NewSize); } | 99 void resizeTypeIDValues(unsigned NewSize) { TypeIDValues.resize(NewSize); } |
95 | 100 |
96 /// Returns the type associated with the given index. | 101 /// Returns the type associated with the given index. |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
221 /// Returns the model for pointer types in ICE. | 226 /// Returns the model for pointer types in ICE. |
222 Ice::Type getIcePointerType() const { | 227 Ice::Type getIcePointerType() const { |
223 return TypeConverter.getIcePointerType(); | 228 return TypeConverter.getIcePointerType(); |
224 } | 229 } |
225 | 230 |
226 private: | 231 private: |
227 // The translator associated with the parser. | 232 // The translator associated with the parser. |
228 Ice::Translator &Translator; | 233 Ice::Translator &Translator; |
229 // The parsed module. | 234 // The parsed module. |
230 OwningPtr<Module> Mod; | 235 OwningPtr<Module> Mod; |
236 // The data layout to use. | |
237 DataLayout DL; | |
231 // The bitcode header. | 238 // The bitcode header. |
232 NaClBitcodeHeader &Header; | 239 NaClBitcodeHeader &Header; |
233 // Converter between LLVM and ICE types. | 240 // Converter between LLVM and ICE types. |
234 Ice::TypeConverter TypeConverter; | 241 Ice::TypeConverter TypeConverter; |
235 // The exit status that should be set to true if an error occurs. | 242 // The exit status that should be set to true if an error occurs. |
236 bool &ErrorStatus; | 243 bool &ErrorStatus; |
237 // The number of errors reported. | 244 // The number of errors reported. |
238 unsigned NumErrors; | 245 unsigned NumErrors; |
239 // The types associated with each type ID. | 246 // The types associated with each type ID. |
240 std::vector<Type *> TypeIDValues; | 247 std::vector<Type *> TypeIDValues; |
(...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
841 // defined in the bitcode file. | 848 // defined in the bitcode file. |
842 std::vector<Ice::Operand *> LocalOperands; | 849 std::vector<Ice::Operand *> LocalOperands; |
843 // Holds the dividing point between local and global absolute value indices. | 850 // Holds the dividing point between local and global absolute value indices. |
844 uint32_t CachedNumGlobalValueIDs; | 851 uint32_t CachedNumGlobalValueIDs; |
845 // True if the last processed instruction was a terminating | 852 // True if the last processed instruction was a terminating |
846 // instruction. | 853 // instruction. |
847 bool InstIsTerminating; | 854 bool InstIsTerminating; |
848 // Upper limit of alignment power allowed by LLVM | 855 // Upper limit of alignment power allowed by LLVM |
849 static const uint64_t AlignPowerLimit = 29; | 856 static const uint64_t AlignPowerLimit = 29; |
850 | 857 |
858 // Extracts the corresponding Alignment to use, given the AlignPower | |
859 // (i.e. 2**AlignPower, or 0 if AlignPower == 0). InstName is the | |
860 // name of the instruction the alignment appears in. | |
Jim Stichnoth
2014/09/10 20:27:15
Document that it returns true on success?
Karl
2014/09/10 21:36:29
Modified to always error recover, even on error, s
| |
861 bool extractAlignment(const char *InstName, uint64_t AlignPower, | |
862 unsigned &Alignment) { | |
863 Alignment = 1; | |
864 if (AlignPower <= AlignPowerLimit) { | |
865 Alignment = (1 << static_cast<unsigned>(AlignPower)) >> 1; | |
866 return true; | |
867 } | |
868 std::string Buffer; | |
869 raw_string_ostream StrBuf(Buffer); | |
870 StrBuf << InstName << " alignment greater than 2**" << AlignPowerLimit | |
871 << ". Found: 2**" << AlignPower; | |
872 Error(StrBuf.str()); | |
873 return false; | |
874 } | |
875 | |
851 virtual bool ParseBlock(unsigned BlockID) LLVM_OVERRIDE; | 876 virtual bool ParseBlock(unsigned BlockID) LLVM_OVERRIDE; |
852 | 877 |
853 virtual void ProcessRecord() LLVM_OVERRIDE; | 878 virtual void ProcessRecord() LLVM_OVERRIDE; |
854 | 879 |
855 virtual void ExitBlock() LLVM_OVERRIDE; | 880 virtual void ExitBlock() LLVM_OVERRIDE; |
856 | 881 |
857 // Creates and appends a new basic block to the list of basic blocks. | 882 // Creates and appends a new basic block to the list of basic blocks. |
858 Ice::CfgNode *InstallNextBasicBlock() { return Func->makeNode(); } | 883 Ice::CfgNode *InstallNextBasicBlock() { return Func->makeNode(); } |
859 | 884 |
860 // Returns the Index-th basic block in the list of basic blocks. | 885 // Returns the Index-th basic block in the list of basic blocks. |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
952 // OpTy, is valid. Returns true if valid. Otherwise generates | 977 // OpTy, is valid. Returns true if valid. Otherwise generates |
953 // error message and returns false. | 978 // error message and returns false. |
954 bool isValidIntegerArithOp(Ice::InstArithmetic::OpKind Op, Ice::Type OpTy) { | 979 bool isValidIntegerArithOp(Ice::InstArithmetic::OpKind Op, Ice::Type OpTy) { |
955 if (Ice::isIntegerArithmeticType(OpTy)) | 980 if (Ice::isIntegerArithmeticType(OpTy)) |
956 return true; | 981 return true; |
957 ReportInvalidBinaryOp(Op, OpTy); | 982 ReportInvalidBinaryOp(Op, OpTy); |
958 return false; | 983 return false; |
959 } | 984 } |
960 | 985 |
961 // Checks if floating arithmetic Op, for type OpTy, is valid. | 986 // Checks if floating arithmetic Op, for type OpTy, is valid. |
962 // Returns false if valid. Otherwise generates an error message and | 987 // Returns true if valid. Otherwise generates an error message and |
963 // returns true. | 988 // returns false; |
964 bool isValidFloatingArithOp(Ice::InstArithmetic::OpKind Op, Ice::Type OpTy) { | 989 bool isValidFloatingArithOp(Ice::InstArithmetic::OpKind Op, Ice::Type OpTy) { |
965 if (Ice::isFloatingType(OpTy)) | 990 if (Ice::isFloatingType(OpTy)) |
966 return true; | 991 return true; |
967 ReportInvalidBinaryOp(Op, OpTy); | 992 ReportInvalidBinaryOp(Op, OpTy); |
968 return false; | 993 return false; |
969 } | 994 } |
970 | 995 |
996 // Checks if the type of operand Op is the valid pointer type, for | |
997 // the given InstructionName. Returns true if valid. Otherwise | |
998 // generates an error message and returns false. | |
999 bool isValidPointerType(Ice::Operand *Op, const char *InstructionName) { | |
1000 Ice::Type PtrType = Context->getIcePointerType(); | |
1001 if (Op->getType() == PtrType) | |
1002 return true; | |
1003 std::string Buffer; | |
1004 raw_string_ostream StrBuf(Buffer); | |
1005 StrBuf << InstructionName << " address not " << PtrType | |
1006 << ". Found: " << Op; | |
1007 Error(StrBuf.str()); | |
1008 return false; | |
1009 } | |
1010 | |
1011 // Checks if loading/storing a value of type Ty is allowed. | |
1012 // Returns true if Valid. Otherwise generates an error message and | |
1013 // returns false. | |
1014 bool isValidLoadStoreType(Ice::Type Ty, const char *InstructionName) { | |
1015 if (isLoadStoreType(Ty)) | |
1016 return true; | |
1017 std::string Buffer; | |
1018 raw_string_ostream StrBuf(Buffer); | |
1019 StrBuf << InstructionName << " type not allowed: " << Ty << "*"; | |
1020 Error(StrBuf.str()); | |
1021 return false; | |
1022 } | |
1023 | |
1024 // Checks if loading/storing wa value of type Ty, is allowed for | |
Jim Stichnoth
2014/09/10 20:27:15
wa --> a
also, no comma
Karl
2014/09/10 21:36:28
Done.
| |
1025 // the given Alignment. Otherwise generates an error message and | |
1026 // returns false. | |
1027 bool isValidLoadStoreAlignment(unsigned Alignment, Ice::Type Ty, | |
1028 const char *InstructionName) { | |
1029 if (!isValidLoadStoreType(Ty, InstructionName)) | |
1030 return false; | |
1031 if (PNaClABIProps::isAllowedAlignment(&Context->getDataLayout(), Alignment, | |
1032 Context->convertToLLVMType(Ty))) | |
1033 return true; | |
1034 std::string Buffer; | |
1035 raw_string_ostream StrBuf(Buffer); | |
1036 StrBuf << InstructionName << " " << Ty << "*: not allowed for alignment " | |
1037 << Alignment; | |
1038 Error(StrBuf.str()); | |
1039 return false; | |
1040 } | |
1041 | |
971 // Reports that the given binary Opcode, for the given type Ty, | 1042 // Reports that the given binary Opcode, for the given type Ty, |
972 // is not understood. | 1043 // is not understood. |
973 void ReportInvalidBinopOpcode(unsigned Opcode, Ice::Type Ty); | 1044 void ReportInvalidBinopOpcode(unsigned Opcode, Ice::Type Ty); |
974 | 1045 |
975 // Takes the PNaCl bitcode binary operator Opcode, and the opcode | 1046 // Takes the PNaCl bitcode binary operator Opcode, and the opcode |
976 // type Ty, and sets Op to the corresponding ICE binary | 1047 // type Ty, and sets Op to the corresponding ICE binary |
977 // opcode. Returns true if able to convert, false otherwise. | 1048 // opcode. Returns true if able to convert, false otherwise. |
978 bool convertBinopOpcode(unsigned Opcode, Ice::Type Ty, | 1049 bool convertBinopOpcode(unsigned Opcode, Ice::Type Ty, |
979 Ice::InstArithmetic::OpKind &Op) { | 1050 Ice::InstArithmetic::OpKind &Op) { |
980 Instruction::BinaryOps LLVMOpcode; | 1051 Instruction::BinaryOps LLVMOpcode; |
(...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1522 if (!isValidRecordSize(2, "function block alloca")) | 1593 if (!isValidRecordSize(2, "function block alloca")) |
1523 return; | 1594 return; |
1524 Ice::Operand *ByteCount = getRelativeOperand(Values[0]); | 1595 Ice::Operand *ByteCount = getRelativeOperand(Values[0]); |
1525 if (ByteCount->getType() != Ice::IceType_i32) { | 1596 if (ByteCount->getType() != Ice::IceType_i32) { |
1526 std::string Buffer; | 1597 std::string Buffer; |
1527 raw_string_ostream StrBuf(Buffer); | 1598 raw_string_ostream StrBuf(Buffer); |
1528 StrBuf << "Alloca on non-i32 value. Found: " << ByteCount; | 1599 StrBuf << "Alloca on non-i32 value. Found: " << ByteCount; |
1529 Error(StrBuf.str()); | 1600 Error(StrBuf.str()); |
1530 return; | 1601 return; |
1531 } | 1602 } |
1532 uint64_t AlignPower = Values[1]; | 1603 unsigned Alignment; |
1533 unsigned Alignment = 1; | 1604 if (!extractAlignment("Alloca", Values[1], Alignment)) { |
1534 if (AlignPower <= AlignPowerLimit) { | |
1535 Alignment = (1 << static_cast<unsigned>(AlignPower)) >> 1; | |
1536 } else { | |
1537 std::string Buffer; | |
1538 raw_string_ostream StrBuf(Buffer); | |
1539 StrBuf << "Alloca on alignment greater than 2**" << AlignPowerLimit | |
1540 << ". Found: 2**" << AlignPower; | |
1541 Error(StrBuf.str()); | |
1542 // TODO(kschimpf) Remove error recovery once implementation complete. | 1605 // TODO(kschimpf) Remove error recovery once implementation complete. |
Jim Stichnoth
2014/09/10 20:27:15
Can this TODO be removed now? Or does it belong i
Karl
2014/09/10 21:36:29
Modified so that the error recovery done inside ex
| |
1606 Alignment = 1; | |
1543 } | 1607 } |
1544 Ice::Variable *Dest = NextInstVar(Context->getIcePointerType()); | 1608 Ice::Variable *Dest = NextInstVar(Context->getIcePointerType()); |
1545 Inst = Ice::InstAlloca::create(Func, ByteCount, Alignment, Dest); | 1609 Inst = Ice::InstAlloca::create(Func, ByteCount, Alignment, Dest); |
1546 break; | 1610 break; |
1547 } | 1611 } |
1612 case naclbitc::FUNC_CODE_INST_LOAD: { | |
1613 // LOAD: [address, align, ty] | |
1614 if (!isValidRecordSize(3, "function block load")) | |
1615 return; | |
1616 Ice::Operand *Address = getRelativeOperand(Values[0]); | |
1617 if (!isValidPointerType(Address, "Load")) | |
1618 return; | |
1619 unsigned Alignment; | |
1620 if (!extractAlignment("Store", Values[1], Alignment)) { | |
Jim Stichnoth
2014/09/10 20:27:15
"Load"
Karl
2014/09/10 21:36:28
Done.
| |
1621 // TODO(kschimpf) Remove error recovery once implementation complete. | |
1622 Alignment = 1; | |
1623 } | |
1624 Ice::Type Ty = Context->convertToIceType(Context->getTypeByID(Values[2])); | |
1625 if (!isValidLoadStoreAlignment(Alignment, Ty, "Load")) | |
1626 return; | |
1627 Ice::Variable *Dest = NextInstVar(Ty); | |
1628 Inst = Ice::InstLoad::create(Func, Dest, Address, Alignment); | |
1629 break; | |
1630 } | |
1631 case naclbitc::FUNC_CODE_INST_STORE: { | |
1632 // STORE: [address, value, align] | |
1633 if (!isValidRecordSize(3, "function block store")) | |
1634 return; | |
1635 Ice::Operand *Address = getRelativeOperand(Values[0]); | |
1636 if (!isValidPointerType(Address, "Store")) | |
1637 return; | |
1638 Ice::Operand *Value = getRelativeOperand(Values[1]); | |
1639 unsigned Alignment; | |
1640 if (!extractAlignment("Store", Values[2], Alignment)) { | |
1641 // TODO(kschimpf) Remove error recovery once implementation complete. | |
1642 Alignment = 1; | |
1643 } | |
1644 if (!isValidLoadStoreAlignment(Alignment, Value->getType(), "Store")) | |
1645 return; | |
1646 Inst = Ice::InstStore::create(Func, Value, Address, Alignment); | |
1647 break; | |
1648 } | |
1548 default: | 1649 default: |
1549 // Generate error message! | 1650 // Generate error message! |
1550 BlockParserBaseClass::ProcessRecord(); | 1651 BlockParserBaseClass::ProcessRecord(); |
1551 break; | 1652 break; |
1552 } | 1653 } |
1553 if (Inst) | 1654 if (Inst) |
1554 CurrentNode->appendInst(Inst); | 1655 CurrentNode->appendInst(Inst); |
1555 } | 1656 } |
1556 | 1657 |
1557 /// Parses constants within a function block. | 1658 /// Parses constants within a function block. |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1836 if (TopLevelBlocks != 1) { | 1937 if (TopLevelBlocks != 1) { |
1837 errs() << IRFilename | 1938 errs() << IRFilename |
1838 << ": Contains more than one module. Found: " << TopLevelBlocks | 1939 << ": Contains more than one module. Found: " << TopLevelBlocks |
1839 << "\n"; | 1940 << "\n"; |
1840 ErrorStatus = true; | 1941 ErrorStatus = true; |
1841 } | 1942 } |
1842 return; | 1943 return; |
1843 } | 1944 } |
1844 | 1945 |
1845 } // end of namespace Ice | 1946 } // end of namespace Ice |
OLD | NEW |