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 // 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 |