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 |
(...skipping 1072 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1083 for (Ice::Type ArgType : Signature.getArgList()) { | 1083 for (Ice::Type ArgType : Signature.getArgList()) { |
1084 Func->addArg(getNextInstVar(ArgType)); | 1084 Func->addArg(getNextInstVar(ArgType)); |
1085 } | 1085 } |
1086 } | 1086 } |
1087 } | 1087 } |
1088 | 1088 |
1089 ~FunctionParser() final {} | 1089 ~FunctionParser() final {} |
1090 | 1090 |
1091 const char *getBlockName() const override { return "function"; } | 1091 const char *getBlockName() const override { return "function"; } |
1092 | 1092 |
1093 Ice::Cfg *getFunc() const { return Func; } | 1093 const std::unique_ptr<Ice::Cfg> &getFunc() const { return Func; } |
1094 | 1094 |
1095 uint32_t getNumGlobalIDs() const { return CachedNumGlobalValueIDs; } | 1095 uint32_t getNumGlobalIDs() const { return CachedNumGlobalValueIDs; } |
1096 | 1096 |
1097 void setNextLocalInstIndex(Ice::Operand *Op) { | 1097 void setNextLocalInstIndex(Ice::Operand *Op) { |
1098 setOperand(NextLocalInstIndex++, Op); | 1098 setOperand(NextLocalInstIndex++, Op); |
1099 } | 1099 } |
1100 | 1100 |
1101 // Set the next constant ID to the given constant C. | 1101 // Set the next constant ID to the given constant C. |
1102 void setNextConstantID(Ice::Constant *C) { setNextLocalInstIndex(C); } | 1102 void setNextConstantID(Ice::Constant *C) { setNextLocalInstIndex(C); } |
1103 | 1103 |
(...skipping 19 matching lines...) Expand all Loading... | |
1123 StrBuf << "Value index " << Index << " not defined!"; | 1123 StrBuf << "Value index " << Index << " not defined!"; |
1124 Error(StrBuf.str()); | 1124 Error(StrBuf.str()); |
1125 report_fatal_error("Unable to continue"); | 1125 report_fatal_error("Unable to continue"); |
1126 } | 1126 } |
1127 return Op; | 1127 return Op; |
1128 } | 1128 } |
1129 | 1129 |
1130 private: | 1130 private: |
1131 Ice::TimerMarker Timer; | 1131 Ice::TimerMarker Timer; |
1132 // The corresponding ICE function defined by the function block. | 1132 // The corresponding ICE function defined by the function block. |
1133 Ice::Cfg *Func; | 1133 std::unique_ptr<Ice::Cfg> Func; |
1134 // The index to the current basic block being built. | 1134 // The index to the current basic block being built. |
1135 uint32_t CurrentBbIndex; | 1135 uint32_t CurrentBbIndex; |
1136 // The basic block being built. | 1136 // The basic block being built. |
1137 Ice::CfgNode *CurrentNode; | 1137 Ice::CfgNode *CurrentNode; |
1138 // The ID for the function. | 1138 // The ID for the function. |
1139 unsigned FcnId; | 1139 unsigned FcnId; |
1140 // The corresponding function declaration. | 1140 // The corresponding function declaration. |
1141 Ice::FunctionDeclaration *FuncDecl; | 1141 Ice::FunctionDeclaration *FuncDecl; |
1142 // Holds the dividing point between local and global absolute value indices. | 1142 // Holds the dividing point between local and global absolute value indices. |
1143 uint32_t CachedNumGlobalValueIDs; | 1143 uint32_t CachedNumGlobalValueIDs; |
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1813 // if the return type is void. In such cases, a placeholder value | 1813 // if the return type is void. In such cases, a placeholder value |
1814 // for the badly formed instruction is not needed. Hence, if Ty is | 1814 // for the badly formed instruction is not needed. Hence, if Ty is |
1815 // void, an error instruction is not appended. | 1815 // void, an error instruction is not appended. |
1816 // TODO(kschimpf) Remove error recovery once implementation complete. | 1816 // TODO(kschimpf) Remove error recovery once implementation complete. |
1817 void appendErrorInstruction(Ice::Type Ty) { | 1817 void appendErrorInstruction(Ice::Type Ty) { |
1818 // Note: we don't worry about downstream translation errors because | 1818 // Note: we don't worry about downstream translation errors because |
1819 // the function will not be translated if any errors occur. | 1819 // the function will not be translated if any errors occur. |
1820 if (Ty == Ice::IceType_void) | 1820 if (Ty == Ice::IceType_void) |
1821 return; | 1821 return; |
1822 Ice::Variable *Var = getNextInstVar(Ty); | 1822 Ice::Variable *Var = getNextInstVar(Ty); |
1823 CurrentNode->appendInst(Ice::InstAssign::create(Func, Var, Var)); | 1823 CurrentNode->appendInst(Ice::InstAssign::create(Func.get(), Var, Var)); |
1824 } | 1824 } |
1825 }; | 1825 }; |
1826 | 1826 |
1827 void FunctionParser::ExitBlock() { | 1827 void FunctionParser::ExitBlock() { |
1828 if (isIRGenerationDisabled()) { | 1828 if (isIRGenerationDisabled()) { |
1829 popTimerIfTimingEachFunction(); | 1829 popTimerIfTimingEachFunction(); |
1830 delete Func; | |
1831 return; | 1830 return; |
1832 } | 1831 } |
1833 // Before translating, check for blocks without instructions, and | 1832 // Before translating, check for blocks without instructions, and |
1834 // insert unreachable. This shouldn't happen, but be safe. | 1833 // insert unreachable. This shouldn't happen, but be safe. |
1835 unsigned Index = 0; | 1834 unsigned Index = 0; |
1836 for (Ice::CfgNode *Node : Func->getNodes()) { | 1835 for (Ice::CfgNode *Node : Func->getNodes()) { |
1837 if (Node->getInsts().empty()) { | 1836 if (Node->getInsts().empty()) { |
1838 std::string Buffer; | 1837 std::string Buffer; |
1839 raw_string_ostream StrBuf(Buffer); | 1838 raw_string_ostream StrBuf(Buffer); |
1840 StrBuf << "Basic block " << Index << " contains no instructions"; | 1839 StrBuf << "Basic block " << Index << " contains no instructions"; |
1841 Error(StrBuf.str()); | 1840 Error(StrBuf.str()); |
1842 // TODO(kschimpf) Remove error recovery once implementation complete. | 1841 // TODO(kschimpf) Remove error recovery once implementation complete. |
1843 Node->appendInst(Ice::InstUnreachable::create(Func)); | 1842 Node->appendInst(Ice::InstUnreachable::create(Func.get())); |
1844 } | 1843 } |
1845 ++Index; | 1844 ++Index; |
1846 } | 1845 } |
1847 Func->computePredecessors(); | 1846 Func->computePredecessors(); |
1848 // Temporarily end per-function timing, which will be resumed by the | 1847 // Temporarily end per-function timing, which will be resumed by the |
1849 // translator function. This is because translation may be done | 1848 // translator function. This is because translation may be done |
1850 // asynchronously in a separate thread. | 1849 // asynchronously in a separate thread. |
1851 popTimerIfTimingEachFunction(); | 1850 popTimerIfTimingEachFunction(); |
1852 // Note: Once any errors have been found, we turn off all | 1851 // Note: Once any errors have been found, we turn off all |
1853 // translation of all remaining functions. This allows use to see | 1852 // translation of all remaining functions. This allows use to see |
1854 // multiple errors, without adding extra checks to the translator | 1853 // multiple errors, without adding extra checks to the translator |
1855 // for such parsing errors. | 1854 // for such parsing errors. |
1856 if (Context->getNumErrors() == 0) | 1855 if (Context->getNumErrors() == 0) { |
1857 getTranslator().translateFcn(Func); | 1856 getTranslator().translateFcn(std::move(Func)); |
1857 // The translator now has ownership of Func. | |
1858 } else { | |
1859 Func.reset(); | |
JF
2015/02/02 20:59:19
This currently does updateTLS(nullptr). Is that ba
Jim Stichnoth
2015/02/03 00:48:51
Done.
| |
1860 } | |
1858 } | 1861 } |
1859 | 1862 |
1860 void FunctionParser::ReportInvalidBinaryOp(Ice::InstArithmetic::OpKind Op, | 1863 void FunctionParser::ReportInvalidBinaryOp(Ice::InstArithmetic::OpKind Op, |
1861 Ice::Type OpTy) { | 1864 Ice::Type OpTy) { |
1862 std::string Buffer; | 1865 std::string Buffer; |
1863 raw_string_ostream StrBuf(Buffer); | 1866 raw_string_ostream StrBuf(Buffer); |
1864 StrBuf << "Invalid operator type for " << Ice::InstArithmetic::getOpName(Op) | 1867 StrBuf << "Invalid operator type for " << Ice::InstArithmetic::getOpName(Op) |
1865 << ". Found " << OpTy; | 1868 << ". Found " << OpTy; |
1866 Error(StrBuf.str()); | 1869 Error(StrBuf.str()); |
1867 } | 1870 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1923 appendErrorInstruction(Type1); | 1926 appendErrorInstruction(Type1); |
1924 return; | 1927 return; |
1925 } | 1928 } |
1926 | 1929 |
1927 Ice::InstArithmetic::OpKind Opcode; | 1930 Ice::InstArithmetic::OpKind Opcode; |
1928 if (!convertBinopOpcode(Values[2], Type1, Opcode)) { | 1931 if (!convertBinopOpcode(Values[2], Type1, Opcode)) { |
1929 appendErrorInstruction(Type1); | 1932 appendErrorInstruction(Type1); |
1930 return; | 1933 return; |
1931 } | 1934 } |
1932 CurrentNode->appendInst(Ice::InstArithmetic::create( | 1935 CurrentNode->appendInst(Ice::InstArithmetic::create( |
1933 Func, Opcode, getNextInstVar(Type1), Op1, Op2)); | 1936 Func.get(), Opcode, getNextInstVar(Type1), Op1, Op2)); |
1934 return; | 1937 return; |
1935 } | 1938 } |
1936 case naclbitc::FUNC_CODE_INST_CAST: { | 1939 case naclbitc::FUNC_CODE_INST_CAST: { |
1937 // CAST: [opval, destty, castopc] | 1940 // CAST: [opval, destty, castopc] |
1938 if (!isValidRecordSize(3, "cast")) | 1941 if (!isValidRecordSize(3, "cast")) |
1939 return; | 1942 return; |
1940 Ice::Operand *Src = getRelativeOperand(Values[0], BaseIndex); | 1943 Ice::Operand *Src = getRelativeOperand(Values[0], BaseIndex); |
1941 Ice::Type CastType = Context->getSimpleTypeByID(Values[1]); | 1944 Ice::Type CastType = Context->getSimpleTypeByID(Values[1]); |
1942 Ice::InstCast::OpKind CastKind; | 1945 Ice::InstCast::OpKind CastKind; |
1943 if (isIRGenerationDisabled()) { | 1946 if (isIRGenerationDisabled()) { |
1944 assert(Src == nullptr); | 1947 assert(Src == nullptr); |
1945 setNextLocalInstIndex(nullptr); | 1948 setNextLocalInstIndex(nullptr); |
1946 return; | 1949 return; |
1947 } | 1950 } |
1948 if (!convertCastOpToIceOp(Values[2], Src->getType(), CastType, CastKind)) { | 1951 if (!convertCastOpToIceOp(Values[2], Src->getType(), CastType, CastKind)) { |
1949 appendErrorInstruction(CastType); | 1952 appendErrorInstruction(CastType); |
1950 return; | 1953 return; |
1951 } | 1954 } |
1952 CurrentNode->appendInst( | 1955 CurrentNode->appendInst(Ice::InstCast::create( |
1953 Ice::InstCast::create(Func, CastKind, getNextInstVar(CastType), Src)); | 1956 Func.get(), CastKind, getNextInstVar(CastType), Src)); |
1954 return; | 1957 return; |
1955 } | 1958 } |
1956 case naclbitc::FUNC_CODE_INST_VSELECT: { | 1959 case naclbitc::FUNC_CODE_INST_VSELECT: { |
1957 // VSELECT: [opval, opval, pred] | 1960 // VSELECT: [opval, opval, pred] |
1958 if (!isValidRecordSize(3, "select")) | 1961 if (!isValidRecordSize(3, "select")) |
1959 return; | 1962 return; |
1960 Ice::Operand *ThenVal = getRelativeOperand(Values[0], BaseIndex); | 1963 Ice::Operand *ThenVal = getRelativeOperand(Values[0], BaseIndex); |
1961 Ice::Operand *ElseVal = getRelativeOperand(Values[1], BaseIndex); | 1964 Ice::Operand *ElseVal = getRelativeOperand(Values[1], BaseIndex); |
1962 Ice::Operand *CondVal = getRelativeOperand(Values[2], BaseIndex); | 1965 Ice::Operand *CondVal = getRelativeOperand(Values[2], BaseIndex); |
1963 if (isIRGenerationDisabled()) { | 1966 if (isIRGenerationDisabled()) { |
(...skipping 28 matching lines...) Expand all Loading... | |
1992 } else if (CondVal->getType() != Ice::IceType_i1) { | 1995 } else if (CondVal->getType() != Ice::IceType_i1) { |
1993 std::string Buffer; | 1996 std::string Buffer; |
1994 raw_string_ostream StrBuf(Buffer); | 1997 raw_string_ostream StrBuf(Buffer); |
1995 StrBuf << "Select condition " << CondVal | 1998 StrBuf << "Select condition " << CondVal |
1996 << " not type i1. Found: " << CondVal->getType(); | 1999 << " not type i1. Found: " << CondVal->getType(); |
1997 Error(StrBuf.str()); | 2000 Error(StrBuf.str()); |
1998 appendErrorInstruction(ThenType); | 2001 appendErrorInstruction(ThenType); |
1999 return; | 2002 return; |
2000 } | 2003 } |
2001 CurrentNode->appendInst(Ice::InstSelect::create( | 2004 CurrentNode->appendInst(Ice::InstSelect::create( |
2002 Func, getNextInstVar(ThenType), CondVal, ThenVal, ElseVal)); | 2005 Func.get(), getNextInstVar(ThenType), CondVal, ThenVal, ElseVal)); |
2003 return; | 2006 return; |
2004 } | 2007 } |
2005 case naclbitc::FUNC_CODE_INST_EXTRACTELT: { | 2008 case naclbitc::FUNC_CODE_INST_EXTRACTELT: { |
2006 // EXTRACTELT: [opval, opval] | 2009 // EXTRACTELT: [opval, opval] |
2007 if (!isValidRecordSize(2, "extract element")) | 2010 if (!isValidRecordSize(2, "extract element")) |
2008 return; | 2011 return; |
2009 Ice::Operand *Vec = getRelativeOperand(Values[0], BaseIndex); | 2012 Ice::Operand *Vec = getRelativeOperand(Values[0], BaseIndex); |
2010 Ice::Operand *Index = getRelativeOperand(Values[1], BaseIndex); | 2013 Ice::Operand *Index = getRelativeOperand(Values[1], BaseIndex); |
2011 if (isIRGenerationDisabled()) { | 2014 if (isIRGenerationDisabled()) { |
2012 assert(Vec == nullptr && Index == nullptr); | 2015 assert(Vec == nullptr && Index == nullptr); |
2013 setNextLocalInstIndex(nullptr); | 2016 setNextLocalInstIndex(nullptr); |
2014 return; | 2017 return; |
2015 } | 2018 } |
2016 Ice::Type VecType = Vec->getType(); | 2019 Ice::Type VecType = Vec->getType(); |
2017 VectorIndexCheckValue IndexCheckValue = validateVectorIndex(Vec, Index); | 2020 VectorIndexCheckValue IndexCheckValue = validateVectorIndex(Vec, Index); |
2018 if (IndexCheckValue != VectorIndexValid) { | 2021 if (IndexCheckValue != VectorIndexValid) { |
2019 std::string Buffer; | 2022 std::string Buffer; |
2020 raw_string_ostream StrBuf(Buffer); | 2023 raw_string_ostream StrBuf(Buffer); |
2021 dumpVectorIndexCheckValue(StrBuf, IndexCheckValue); | 2024 dumpVectorIndexCheckValue(StrBuf, IndexCheckValue); |
2022 StrBuf << ": extractelement " << VecType << " " << *Vec << ", " | 2025 StrBuf << ": extractelement " << VecType << " " << *Vec << ", " |
2023 << Index->getType() << " " << *Index; | 2026 << Index->getType() << " " << *Index; |
2024 Error(StrBuf.str()); | 2027 Error(StrBuf.str()); |
2025 appendErrorInstruction(VecType); | 2028 appendErrorInstruction(VecType); |
2026 return; | 2029 return; |
2027 } | 2030 } |
2028 CurrentNode->appendInst(Ice::InstExtractElement::create( | 2031 CurrentNode->appendInst(Ice::InstExtractElement::create( |
2029 Func, getNextInstVar(typeElementType(VecType)), Vec, Index)); | 2032 Func.get(), getNextInstVar(typeElementType(VecType)), Vec, Index)); |
2030 return; | 2033 return; |
2031 } | 2034 } |
2032 case naclbitc::FUNC_CODE_INST_INSERTELT: { | 2035 case naclbitc::FUNC_CODE_INST_INSERTELT: { |
2033 // INSERTELT: [opval, opval, opval] | 2036 // INSERTELT: [opval, opval, opval] |
2034 if (!isValidRecordSize(3, "insert element")) | 2037 if (!isValidRecordSize(3, "insert element")) |
2035 return; | 2038 return; |
2036 Ice::Operand *Vec = getRelativeOperand(Values[0], BaseIndex); | 2039 Ice::Operand *Vec = getRelativeOperand(Values[0], BaseIndex); |
2037 Ice::Operand *Elt = getRelativeOperand(Values[1], BaseIndex); | 2040 Ice::Operand *Elt = getRelativeOperand(Values[1], BaseIndex); |
2038 Ice::Operand *Index = getRelativeOperand(Values[2], BaseIndex); | 2041 Ice::Operand *Index = getRelativeOperand(Values[2], BaseIndex); |
2039 if (isIRGenerationDisabled()) { | 2042 if (isIRGenerationDisabled()) { |
2040 assert(Vec == nullptr && Elt == nullptr && Index == nullptr); | 2043 assert(Vec == nullptr && Elt == nullptr && Index == nullptr); |
2041 setNextLocalInstIndex(nullptr); | 2044 setNextLocalInstIndex(nullptr); |
2042 return; | 2045 return; |
2043 } | 2046 } |
2044 Ice::Type VecType = Vec->getType(); | 2047 Ice::Type VecType = Vec->getType(); |
2045 VectorIndexCheckValue IndexCheckValue = validateVectorIndex(Vec, Index); | 2048 VectorIndexCheckValue IndexCheckValue = validateVectorIndex(Vec, Index); |
2046 if (IndexCheckValue != VectorIndexValid) { | 2049 if (IndexCheckValue != VectorIndexValid) { |
2047 std::string Buffer; | 2050 std::string Buffer; |
2048 raw_string_ostream StrBuf(Buffer); | 2051 raw_string_ostream StrBuf(Buffer); |
2049 dumpVectorIndexCheckValue(StrBuf, IndexCheckValue); | 2052 dumpVectorIndexCheckValue(StrBuf, IndexCheckValue); |
2050 StrBuf << ": insertelement " << VecType << " " << *Vec << ", " | 2053 StrBuf << ": insertelement " << VecType << " " << *Vec << ", " |
2051 << Elt->getType() << " " << *Elt << ", " << Index->getType() << " " | 2054 << Elt->getType() << " " << *Elt << ", " << Index->getType() << " " |
2052 << *Index; | 2055 << *Index; |
2053 Error(StrBuf.str()); | 2056 Error(StrBuf.str()); |
2054 appendErrorInstruction(Elt->getType()); | 2057 appendErrorInstruction(Elt->getType()); |
2055 return; | 2058 return; |
2056 } | 2059 } |
2057 CurrentNode->appendInst(Ice::InstInsertElement::create( | 2060 CurrentNode->appendInst(Ice::InstInsertElement::create( |
2058 Func, getNextInstVar(VecType), Vec, Elt, Index)); | 2061 Func.get(), getNextInstVar(VecType), Vec, Elt, Index)); |
2059 return; | 2062 return; |
2060 } | 2063 } |
2061 case naclbitc::FUNC_CODE_INST_CMP2: { | 2064 case naclbitc::FUNC_CODE_INST_CMP2: { |
2062 // CMP2: [opval, opval, pred] | 2065 // CMP2: [opval, opval, pred] |
2063 if (!isValidRecordSize(3, "compare")) | 2066 if (!isValidRecordSize(3, "compare")) |
2064 return; | 2067 return; |
2065 Ice::Operand *Op1 = getRelativeOperand(Values[0], BaseIndex); | 2068 Ice::Operand *Op1 = getRelativeOperand(Values[0], BaseIndex); |
2066 Ice::Operand *Op2 = getRelativeOperand(Values[1], BaseIndex); | 2069 Ice::Operand *Op2 = getRelativeOperand(Values[1], BaseIndex); |
2067 if (isIRGenerationDisabled()) { | 2070 if (isIRGenerationDisabled()) { |
2068 assert(Op1 == nullptr && Op2 == nullptr); | 2071 assert(Op1 == nullptr && Op2 == nullptr); |
(...skipping 24 matching lines...) Expand all Loading... | |
2093 Ice::InstIcmp::ICond Cond; | 2096 Ice::InstIcmp::ICond Cond; |
2094 if (!convertNaClBitcICmpOpToIce(Values[2], Cond)) { | 2097 if (!convertNaClBitcICmpOpToIce(Values[2], Cond)) { |
2095 std::string Buffer; | 2098 std::string Buffer; |
2096 raw_string_ostream StrBuf(Buffer); | 2099 raw_string_ostream StrBuf(Buffer); |
2097 StrBuf << "Compare record contains unknown integer predicate index: " | 2100 StrBuf << "Compare record contains unknown integer predicate index: " |
2098 << Values[2]; | 2101 << Values[2]; |
2099 Error(StrBuf.str()); | 2102 Error(StrBuf.str()); |
2100 appendErrorInstruction(DestType); | 2103 appendErrorInstruction(DestType); |
2101 } | 2104 } |
2102 CurrentNode->appendInst( | 2105 CurrentNode->appendInst( |
2103 Ice::InstIcmp::create(Func, Cond, Dest, Op1, Op2)); | 2106 Ice::InstIcmp::create(Func.get(), Cond, Dest, Op1, Op2)); |
2104 } else if (isFloatingType(Op1Type)) { | 2107 } else if (isFloatingType(Op1Type)) { |
2105 Ice::InstFcmp::FCond Cond; | 2108 Ice::InstFcmp::FCond Cond; |
2106 if (!convertNaClBitcFCompOpToIce(Values[2], Cond)) { | 2109 if (!convertNaClBitcFCompOpToIce(Values[2], Cond)) { |
2107 std::string Buffer; | 2110 std::string Buffer; |
2108 raw_string_ostream StrBuf(Buffer); | 2111 raw_string_ostream StrBuf(Buffer); |
2109 StrBuf << "Compare record contains unknown float predicate index: " | 2112 StrBuf << "Compare record contains unknown float predicate index: " |
2110 << Values[2]; | 2113 << Values[2]; |
2111 Error(StrBuf.str()); | 2114 Error(StrBuf.str()); |
2112 appendErrorInstruction(DestType); | 2115 appendErrorInstruction(DestType); |
2113 } | 2116 } |
2114 CurrentNode->appendInst( | 2117 CurrentNode->appendInst( |
2115 Ice::InstFcmp::create(Func, Cond, Dest, Op1, Op2)); | 2118 Ice::InstFcmp::create(Func.get(), Cond, Dest, Op1, Op2)); |
2116 } else { | 2119 } else { |
2117 // Not sure this can happen, but be safe. | 2120 // Not sure this can happen, but be safe. |
2118 std::string Buffer; | 2121 std::string Buffer; |
2119 raw_string_ostream StrBuf(Buffer); | 2122 raw_string_ostream StrBuf(Buffer); |
2120 StrBuf << "Compare on type not understood: " << Op1Type; | 2123 StrBuf << "Compare on type not understood: " << Op1Type; |
2121 Error(StrBuf.str()); | 2124 Error(StrBuf.str()); |
2122 appendErrorInstruction(DestType); | 2125 appendErrorInstruction(DestType); |
2123 return; | 2126 return; |
2124 } | 2127 } |
2125 return; | 2128 return; |
2126 } | 2129 } |
2127 case naclbitc::FUNC_CODE_INST_RET: { | 2130 case naclbitc::FUNC_CODE_INST_RET: { |
2128 // RET: [opval?] | 2131 // RET: [opval?] |
2129 if (!isValidRecordSizeInRange(0, 1, "return")) | 2132 if (!isValidRecordSizeInRange(0, 1, "return")) |
2130 return; | 2133 return; |
2131 if (Values.empty()) { | 2134 if (Values.empty()) { |
2132 if (isIRGenerationDisabled()) | 2135 if (isIRGenerationDisabled()) |
2133 return; | 2136 return; |
2134 CurrentNode->appendInst(Ice::InstRet::create(Func)); | 2137 CurrentNode->appendInst(Ice::InstRet::create(Func.get())); |
2135 } else { | 2138 } else { |
2136 Ice::Operand *RetVal = getRelativeOperand(Values[0], BaseIndex); | 2139 Ice::Operand *RetVal = getRelativeOperand(Values[0], BaseIndex); |
2137 if (isIRGenerationDisabled()) { | 2140 if (isIRGenerationDisabled()) { |
2138 assert(RetVal == nullptr); | 2141 assert(RetVal == nullptr); |
2139 return; | 2142 return; |
2140 } | 2143 } |
2141 CurrentNode->appendInst(Ice::InstRet::create(Func, RetVal)); | 2144 CurrentNode->appendInst(Ice::InstRet::create(Func.get(), RetVal)); |
2142 } | 2145 } |
2143 InstIsTerminating = true; | 2146 InstIsTerminating = true; |
2144 return; | 2147 return; |
2145 } | 2148 } |
2146 case naclbitc::FUNC_CODE_INST_BR: { | 2149 case naclbitc::FUNC_CODE_INST_BR: { |
2147 if (Values.size() == 1) { | 2150 if (Values.size() == 1) { |
2148 // BR: [bb#] | 2151 // BR: [bb#] |
2149 if (isIRGenerationDisabled()) | 2152 if (isIRGenerationDisabled()) |
2150 return; | 2153 return; |
2151 Ice::CfgNode *Block = getBranchBasicBlock(Values[0]); | 2154 Ice::CfgNode *Block = getBranchBasicBlock(Values[0]); |
2152 if (Block == nullptr) | 2155 if (Block == nullptr) |
2153 return; | 2156 return; |
2154 CurrentNode->appendInst(Ice::InstBr::create(Func, Block)); | 2157 CurrentNode->appendInst(Ice::InstBr::create(Func.get(), Block)); |
2155 } else { | 2158 } else { |
2156 // BR: [bb#, bb#, opval] | 2159 // BR: [bb#, bb#, opval] |
2157 if (!isValidRecordSize(3, "branch")) | 2160 if (!isValidRecordSize(3, "branch")) |
2158 return; | 2161 return; |
2159 Ice::Operand *Cond = getRelativeOperand(Values[2], BaseIndex); | 2162 Ice::Operand *Cond = getRelativeOperand(Values[2], BaseIndex); |
2160 if (isIRGenerationDisabled()) { | 2163 if (isIRGenerationDisabled()) { |
2161 assert(Cond == nullptr); | 2164 assert(Cond == nullptr); |
2162 return; | 2165 return; |
2163 } | 2166 } |
2164 if (Cond->getType() != Ice::IceType_i1) { | 2167 if (Cond->getType() != Ice::IceType_i1) { |
2165 std::string Buffer; | 2168 std::string Buffer; |
2166 raw_string_ostream StrBuf(Buffer); | 2169 raw_string_ostream StrBuf(Buffer); |
2167 StrBuf << "Branch condition " << *Cond | 2170 StrBuf << "Branch condition " << *Cond |
2168 << " not i1. Found: " << Cond->getType(); | 2171 << " not i1. Found: " << Cond->getType(); |
2169 Error(StrBuf.str()); | 2172 Error(StrBuf.str()); |
2170 return; | 2173 return; |
2171 } | 2174 } |
2172 Ice::CfgNode *ThenBlock = getBranchBasicBlock(Values[0]); | 2175 Ice::CfgNode *ThenBlock = getBranchBasicBlock(Values[0]); |
2173 Ice::CfgNode *ElseBlock = getBranchBasicBlock(Values[1]); | 2176 Ice::CfgNode *ElseBlock = getBranchBasicBlock(Values[1]); |
2174 if (ThenBlock == nullptr || ElseBlock == nullptr) | 2177 if (ThenBlock == nullptr || ElseBlock == nullptr) |
2175 return; | 2178 return; |
2176 CurrentNode->appendInst( | 2179 CurrentNode->appendInst( |
2177 Ice::InstBr::create(Func, Cond, ThenBlock, ElseBlock)); | 2180 Ice::InstBr::create(Func.get(), Cond, ThenBlock, ElseBlock)); |
2178 } | 2181 } |
2179 InstIsTerminating = true; | 2182 InstIsTerminating = true; |
2180 return; | 2183 return; |
2181 } | 2184 } |
2182 case naclbitc::FUNC_CODE_INST_SWITCH: { | 2185 case naclbitc::FUNC_CODE_INST_SWITCH: { |
2183 // SWITCH: [Condty, Cond, BbIndex, NumCases Case ...] | 2186 // SWITCH: [Condty, Cond, BbIndex, NumCases Case ...] |
2184 // where Case = [1, 1, Value, BbIndex]. | 2187 // where Case = [1, 1, Value, BbIndex]. |
2185 // | 2188 // |
2186 // Note: Unlike most instructions, we don't infer the type of | 2189 // Note: Unlike most instructions, we don't infer the type of |
2187 // Cond, but provide it as a separate field. There are also | 2190 // Cond, but provide it as a separate field. There are also |
(...skipping 26 matching lines...) Expand all Loading... | |
2214 return; | 2217 return; |
2215 } | 2218 } |
2216 Ice::CfgNode *DefaultLabel = | 2219 Ice::CfgNode *DefaultLabel = |
2217 isIRGenDisabled ? nullptr : getBranchBasicBlock(Values[2]); | 2220 isIRGenDisabled ? nullptr : getBranchBasicBlock(Values[2]); |
2218 unsigned NumCases = Values[3]; | 2221 unsigned NumCases = Values[3]; |
2219 | 2222 |
2220 // Now recognize each of the cases. | 2223 // Now recognize each of the cases. |
2221 if (!isValidRecordSize(4 + NumCases * 4, "switch")) | 2224 if (!isValidRecordSize(4 + NumCases * 4, "switch")) |
2222 return; | 2225 return; |
2223 Ice::InstSwitch *Switch = | 2226 Ice::InstSwitch *Switch = |
2224 isIRGenDisabled ? nullptr : Ice::InstSwitch::create(Func, NumCases, | 2227 isIRGenDisabled |
2225 Cond, DefaultLabel); | 2228 ? nullptr |
2229 : Ice::InstSwitch::create(Func.get(), NumCases, Cond, DefaultLabel); | |
2226 unsigned ValCaseIndex = 4; // index to beginning of case entry. | 2230 unsigned ValCaseIndex = 4; // index to beginning of case entry. |
2227 for (unsigned CaseIndex = 0; CaseIndex < NumCases; | 2231 for (unsigned CaseIndex = 0; CaseIndex < NumCases; |
2228 ++CaseIndex, ValCaseIndex += 4) { | 2232 ++CaseIndex, ValCaseIndex += 4) { |
2229 if (Values[ValCaseIndex] != 1 || Values[ValCaseIndex + 1] != 1) { | 2233 if (Values[ValCaseIndex] != 1 || Values[ValCaseIndex + 1] != 1) { |
2230 std::string Buffer; | 2234 std::string Buffer; |
2231 raw_string_ostream StrBuf(Buffer); | 2235 raw_string_ostream StrBuf(Buffer); |
2232 StrBuf << "Sequence [1, 1, value, label] expected for case entry " | 2236 StrBuf << "Sequence [1, 1, value, label] expected for case entry " |
2233 << "in switch record. (at index" << ValCaseIndex << ")"; | 2237 << "in switch record. (at index" << ValCaseIndex << ")"; |
2234 Error(StrBuf.str()); | 2238 Error(StrBuf.str()); |
2235 return; | 2239 return; |
(...skipping 10 matching lines...) Expand all Loading... | |
2246 CurrentNode->appendInst(Switch); | 2250 CurrentNode->appendInst(Switch); |
2247 InstIsTerminating = true; | 2251 InstIsTerminating = true; |
2248 return; | 2252 return; |
2249 } | 2253 } |
2250 case naclbitc::FUNC_CODE_INST_UNREACHABLE: { | 2254 case naclbitc::FUNC_CODE_INST_UNREACHABLE: { |
2251 // UNREACHABLE: [] | 2255 // UNREACHABLE: [] |
2252 if (!isValidRecordSize(0, "unreachable")) | 2256 if (!isValidRecordSize(0, "unreachable")) |
2253 return; | 2257 return; |
2254 if (isIRGenerationDisabled()) | 2258 if (isIRGenerationDisabled()) |
2255 return; | 2259 return; |
2256 CurrentNode->appendInst(Ice::InstUnreachable::create(Func)); | 2260 CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get())); |
2257 InstIsTerminating = true; | 2261 InstIsTerminating = true; |
2258 return; | 2262 return; |
2259 } | 2263 } |
2260 case naclbitc::FUNC_CODE_INST_PHI: { | 2264 case naclbitc::FUNC_CODE_INST_PHI: { |
2261 // PHI: [ty, val1, bb1, ..., valN, bbN] for n >= 2. | 2265 // PHI: [ty, val1, bb1, ..., valN, bbN] for n >= 2. |
2262 if (!isValidRecordSizeAtLeast(3, "phi")) | 2266 if (!isValidRecordSizeAtLeast(3, "phi")) |
2263 return; | 2267 return; |
2264 Ice::Type Ty = Context->getSimpleTypeByID(Values[0]); | 2268 Ice::Type Ty = Context->getSimpleTypeByID(Values[0]); |
2265 if ((Values.size() & 0x1) == 0) { | 2269 if ((Values.size() & 0x1) == 0) { |
2266 // Not an odd number of values. | 2270 // Not an odd number of values. |
(...skipping 11 matching lines...) Expand all Loading... | |
2278 if (isIRGenerationDisabled()) { | 2282 if (isIRGenerationDisabled()) { |
2279 // Verify arguments are defined before quitting. | 2283 // Verify arguments are defined before quitting. |
2280 for (unsigned i = 1; i < Values.size(); i += 2) { | 2284 for (unsigned i = 1; i < Values.size(); i += 2) { |
2281 assert(getRelativeOperand(NaClDecodeSignRotatedValue(Values[i]), | 2285 assert(getRelativeOperand(NaClDecodeSignRotatedValue(Values[i]), |
2282 BaseIndex) == nullptr); | 2286 BaseIndex) == nullptr); |
2283 } | 2287 } |
2284 setNextLocalInstIndex(nullptr); | 2288 setNextLocalInstIndex(nullptr); |
2285 return; | 2289 return; |
2286 } | 2290 } |
2287 Ice::Variable *Dest = getNextInstVar(Ty); | 2291 Ice::Variable *Dest = getNextInstVar(Ty); |
2288 Ice::InstPhi *Phi = Ice::InstPhi::create(Func, Values.size() >> 1, Dest); | 2292 Ice::InstPhi *Phi = |
2293 Ice::InstPhi::create(Func.get(), Values.size() >> 1, Dest); | |
2289 for (unsigned i = 1; i < Values.size(); i += 2) { | 2294 for (unsigned i = 1; i < Values.size(); i += 2) { |
2290 Ice::Operand *Op = | 2295 Ice::Operand *Op = |
2291 getRelativeOperand(NaClDecodeSignRotatedValue(Values[i]), BaseIndex); | 2296 getRelativeOperand(NaClDecodeSignRotatedValue(Values[i]), BaseIndex); |
2292 if (Op->getType() != Ty) { | 2297 if (Op->getType() != Ty) { |
2293 std::string Buffer; | 2298 std::string Buffer; |
2294 raw_string_ostream StrBuf(Buffer); | 2299 raw_string_ostream StrBuf(Buffer); |
2295 StrBuf << "Value " << *Op << " not type " << Ty | 2300 StrBuf << "Value " << *Op << " not type " << Ty |
2296 << " in phi instruction. Found: " << Op->getType(); | 2301 << " in phi instruction. Found: " << Op->getType(); |
2297 Error(StrBuf.str()); | 2302 Error(StrBuf.str()); |
2298 appendErrorInstruction(Ty); | 2303 appendErrorInstruction(Ty); |
(...skipping 18 matching lines...) Expand all Loading... | |
2317 } | 2322 } |
2318 Ice::Type PtrTy = Ice::getPointerType(); | 2323 Ice::Type PtrTy = Ice::getPointerType(); |
2319 if (ByteCount->getType() != Ice::IceType_i32) { | 2324 if (ByteCount->getType() != Ice::IceType_i32) { |
2320 std::string Buffer; | 2325 std::string Buffer; |
2321 raw_string_ostream StrBuf(Buffer); | 2326 raw_string_ostream StrBuf(Buffer); |
2322 StrBuf << "Alloca on non-i32 value. Found: " << *ByteCount; | 2327 StrBuf << "Alloca on non-i32 value. Found: " << *ByteCount; |
2323 Error(StrBuf.str()); | 2328 Error(StrBuf.str()); |
2324 appendErrorInstruction(PtrTy); | 2329 appendErrorInstruction(PtrTy); |
2325 return; | 2330 return; |
2326 } | 2331 } |
2327 CurrentNode->appendInst(Ice::InstAlloca::create(Func, ByteCount, Alignment, | 2332 CurrentNode->appendInst(Ice::InstAlloca::create( |
2328 getNextInstVar(PtrTy))); | 2333 Func.get(), ByteCount, Alignment, getNextInstVar(PtrTy))); |
2329 return; | 2334 return; |
2330 } | 2335 } |
2331 case naclbitc::FUNC_CODE_INST_LOAD: { | 2336 case naclbitc::FUNC_CODE_INST_LOAD: { |
2332 // LOAD: [address, align, ty] | 2337 // LOAD: [address, align, ty] |
2333 if (!isValidRecordSize(3, "load")) | 2338 if (!isValidRecordSize(3, "load")) |
2334 return; | 2339 return; |
2335 Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex); | 2340 Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex); |
2336 Ice::Type Ty = Context->getSimpleTypeByID(Values[2]); | 2341 Ice::Type Ty = Context->getSimpleTypeByID(Values[2]); |
2337 uint32_t Alignment; | 2342 uint32_t Alignment; |
2338 extractAlignment("Load", Values[1], Alignment); | 2343 extractAlignment("Load", Values[1], Alignment); |
2339 if (isIRGenerationDisabled()) { | 2344 if (isIRGenerationDisabled()) { |
2340 assert(Address == nullptr); | 2345 assert(Address == nullptr); |
2341 setNextLocalInstIndex(nullptr); | 2346 setNextLocalInstIndex(nullptr); |
2342 return; | 2347 return; |
2343 } | 2348 } |
2344 if (!isValidPointerType(Address, "Load")) { | 2349 if (!isValidPointerType(Address, "Load")) { |
2345 appendErrorInstruction(Ty); | 2350 appendErrorInstruction(Ty); |
2346 return; | 2351 return; |
2347 } | 2352 } |
2348 if (!isValidLoadStoreAlignment(Alignment, Ty, "Load")) { | 2353 if (!isValidLoadStoreAlignment(Alignment, Ty, "Load")) { |
2349 appendErrorInstruction(Ty); | 2354 appendErrorInstruction(Ty); |
2350 return; | 2355 return; |
2351 } | 2356 } |
2352 CurrentNode->appendInst( | 2357 CurrentNode->appendInst(Ice::InstLoad::create( |
2353 Ice::InstLoad::create(Func, getNextInstVar(Ty), Address, Alignment)); | 2358 Func.get(), getNextInstVar(Ty), Address, Alignment)); |
2354 return; | 2359 return; |
2355 } | 2360 } |
2356 case naclbitc::FUNC_CODE_INST_STORE: { | 2361 case naclbitc::FUNC_CODE_INST_STORE: { |
2357 // STORE: [address, value, align] | 2362 // STORE: [address, value, align] |
2358 if (!isValidRecordSize(3, "store")) | 2363 if (!isValidRecordSize(3, "store")) |
2359 return; | 2364 return; |
2360 Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex); | 2365 Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex); |
2361 Ice::Operand *Value = getRelativeOperand(Values[1], BaseIndex); | 2366 Ice::Operand *Value = getRelativeOperand(Values[1], BaseIndex); |
2362 uint32_t Alignment; | 2367 uint32_t Alignment; |
2363 extractAlignment("Store", Values[2], Alignment); | 2368 extractAlignment("Store", Values[2], Alignment); |
2364 if (isIRGenerationDisabled()) { | 2369 if (isIRGenerationDisabled()) { |
2365 assert(Address == nullptr && Value == nullptr); | 2370 assert(Address == nullptr && Value == nullptr); |
2366 return; | 2371 return; |
2367 } | 2372 } |
2368 if (!isValidPointerType(Address, "Store")) | 2373 if (!isValidPointerType(Address, "Store")) |
2369 return; | 2374 return; |
2370 if (!isValidLoadStoreAlignment(Alignment, Value->getType(), "Store")) | 2375 if (!isValidLoadStoreAlignment(Alignment, Value->getType(), "Store")) |
2371 return; | 2376 return; |
2372 CurrentNode->appendInst( | 2377 CurrentNode->appendInst( |
2373 Ice::InstStore::create(Func, Value, Address, Alignment)); | 2378 Ice::InstStore::create(Func.get(), Value, Address, Alignment)); |
2374 return; | 2379 return; |
2375 } | 2380 } |
2376 case naclbitc::FUNC_CODE_INST_CALL: | 2381 case naclbitc::FUNC_CODE_INST_CALL: |
2377 case naclbitc::FUNC_CODE_INST_CALL_INDIRECT: { | 2382 case naclbitc::FUNC_CODE_INST_CALL_INDIRECT: { |
2378 // CALL: [cc, fnid, arg0, arg1...] | 2383 // CALL: [cc, fnid, arg0, arg1...] |
2379 // CALL_INDIRECT: [cc, fn, returnty, args...] | 2384 // CALL_INDIRECT: [cc, fn, returnty, args...] |
2380 // | 2385 // |
2381 // Note: The difference between CALL and CALL_INDIRECT is that | 2386 // Note: The difference between CALL and CALL_INDIRECT is that |
2382 // CALL has a reference to an explicit function declaration, while | 2387 // CALL has a reference to an explicit function declaration, while |
2383 // the CALL_INDIRECT is just an address. For CALL, we can infer | 2388 // the CALL_INDIRECT is just an address. For CALL, we can infer |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2452 setNextLocalInstIndex(nullptr); | 2457 setNextLocalInstIndex(nullptr); |
2453 return; | 2458 return; |
2454 } | 2459 } |
2455 | 2460 |
2456 // Create the call instruction. | 2461 // Create the call instruction. |
2457 Ice::Variable *Dest = (ReturnType == Ice::IceType_void) | 2462 Ice::Variable *Dest = (ReturnType == Ice::IceType_void) |
2458 ? nullptr | 2463 ? nullptr |
2459 : getNextInstVar(ReturnType); | 2464 : getNextInstVar(ReturnType); |
2460 Ice::InstCall *Inst = nullptr; | 2465 Ice::InstCall *Inst = nullptr; |
2461 if (IntrinsicInfo) { | 2466 if (IntrinsicInfo) { |
2462 Inst = Ice::InstIntrinsicCall::create(Func, NumParams, Dest, Callee, | 2467 Inst = Ice::InstIntrinsicCall::create(Func.get(), NumParams, Dest, Callee, |
2463 IntrinsicInfo->Info); | 2468 IntrinsicInfo->Info); |
2464 } else { | 2469 } else { |
2465 Inst = Ice::InstCall::create(Func, NumParams, Dest, Callee, IsTailCall); | 2470 Inst = Ice::InstCall::create(Func.get(), NumParams, Dest, Callee, |
2471 IsTailCall); | |
2466 } | 2472 } |
2467 | 2473 |
2468 // Add parameters. | 2474 // Add parameters. |
2469 for (Ice::SizeT ParamIndex = 0; ParamIndex < NumParams; ++ParamIndex) { | 2475 for (Ice::SizeT ParamIndex = 0; ParamIndex < NumParams; ++ParamIndex) { |
2470 Inst->addArg( | 2476 Inst->addArg( |
2471 getRelativeOperand(Values[ParamsStartIndex + ParamIndex], BaseIndex)); | 2477 getRelativeOperand(Values[ParamsStartIndex + ParamIndex], BaseIndex)); |
2472 } | 2478 } |
2473 | 2479 |
2474 // If intrinsic call, validate call signature. | 2480 // If intrinsic call, validate call signature. |
2475 if (IntrinsicInfo) { | 2481 if (IntrinsicInfo) { |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2696 reportUnableToAssign("instruction", Index, Name); | 2702 reportUnableToAssign("instruction", Index, Name); |
2697 // TODO(kschimpf) Remove error recovery once implementation complete. | 2703 // TODO(kschimpf) Remove error recovery once implementation complete. |
2698 return; | 2704 return; |
2699 } | 2705 } |
2700 if (isIRGenerationDisabled()) | 2706 if (isIRGenerationDisabled()) |
2701 return; | 2707 return; |
2702 Ice::Operand *Op = getFunctionParser()->getOperand(Index); | 2708 Ice::Operand *Op = getFunctionParser()->getOperand(Index); |
2703 if (Ice::Variable *V = dyn_cast<Ice::Variable>(Op)) { | 2709 if (Ice::Variable *V = dyn_cast<Ice::Variable>(Op)) { |
2704 if (ALLOW_DUMP) { | 2710 if (ALLOW_DUMP) { |
2705 std::string Nm(Name.data(), Name.size()); | 2711 std::string Nm(Name.data(), Name.size()); |
2706 V->setName(getFunctionParser()->getFunc(), Nm); | 2712 V->setName(getFunctionParser()->getFunc().get(), Nm); |
2707 } | 2713 } |
2708 } else { | 2714 } else { |
2709 reportUnableToAssign("variable", Index, Name); | 2715 reportUnableToAssign("variable", Index, Name); |
2710 } | 2716 } |
2711 } | 2717 } |
2712 | 2718 |
2713 void FunctionValuesymtabParser::setBbName(uint64_t Index, StringType &Name) { | 2719 void FunctionValuesymtabParser::setBbName(uint64_t Index, StringType &Name) { |
2714 if (isIRGenerationDisabled()) | 2720 if (isIRGenerationDisabled()) |
2715 return; | 2721 return; |
2716 if (Index >= getFunctionParser()->getFunc()->getNumNodes()) { | 2722 if (Index >= getFunctionParser()->getFunc()->getNumNodes()) { |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2977 | 2983 |
2978 if (TopLevelBlocks != 1) { | 2984 if (TopLevelBlocks != 1) { |
2979 errs() << IRFilename | 2985 errs() << IRFilename |
2980 << ": Contains more than one module. Found: " << TopLevelBlocks | 2986 << ": Contains more than one module. Found: " << TopLevelBlocks |
2981 << "\n"; | 2987 << "\n"; |
2982 ErrorStatus.assign(EC_Bitcode); | 2988 ErrorStatus.assign(EC_Bitcode); |
2983 } | 2989 } |
2984 } | 2990 } |
2985 | 2991 |
2986 } // end of namespace Ice | 2992 } // end of namespace Ice |
OLD | NEW |