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 "llvm/ADT/SmallString.h" | 15 #include "llvm/ADT/SmallString.h" |
| 16 #include "llvm/Analysis/NaCl/PNaClABIProps.h" | |
| 17 #include "llvm/Bitcode/NaCl/NaClBitcodeDecoders.h" | 16 #include "llvm/Bitcode/NaCl/NaClBitcodeDecoders.h" |
| 18 #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h" | 17 #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h" |
| 19 #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" | 18 #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" |
| 20 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" | 19 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" |
| 21 #include "llvm/IR/Constants.h" | 20 #include "llvm/IR/Constants.h" |
| 22 #include "llvm/IR/DataLayout.h" | |
| 23 #include "llvm/IR/LLVMContext.h" | 21 #include "llvm/IR/LLVMContext.h" |
| 24 #include "llvm/IR/Module.h" | 22 #include "llvm/IR/Module.h" |
| 25 #include "llvm/Support/Format.h" | 23 #include "llvm/Support/Format.h" |
| 26 #include "llvm/Support/MemoryBuffer.h" | 24 #include "llvm/Support/MemoryBuffer.h" |
| 27 #include "llvm/Support/raw_ostream.h" | 25 #include "llvm/Support/raw_ostream.h" |
| 28 | 26 |
| 29 #include "IceCfg.h" | 27 #include "IceCfg.h" |
| 30 #include "IceCfgNode.h" | 28 #include "IceCfgNode.h" |
| 31 #include "IceClFlags.h" | 29 #include "IceClFlags.h" |
| 32 #include "IceDefs.h" | 30 #include "IceDefs.h" |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 168 TopLevelParser(const TopLevelParser &) = delete; | 166 TopLevelParser(const TopLevelParser &) = delete; |
| 169 TopLevelParser &operator=(const TopLevelParser &) = delete; | 167 TopLevelParser &operator=(const TopLevelParser &) = delete; |
| 170 | 168 |
| 171 public: | 169 public: |
| 172 typedef std::vector<Ice::FunctionDeclaration *> FunctionDeclarationListType; | 170 typedef std::vector<Ice::FunctionDeclaration *> FunctionDeclarationListType; |
| 173 | 171 |
| 174 TopLevelParser(Ice::Translator &Translator, const std::string &InputName, | 172 TopLevelParser(Ice::Translator &Translator, const std::string &InputName, |
| 175 NaClBitcodeHeader &Header, NaClBitstreamCursor &Cursor, | 173 NaClBitcodeHeader &Header, NaClBitstreamCursor &Cursor, |
| 176 bool &ErrorStatus) | 174 bool &ErrorStatus) |
| 177 : NaClBitcodeParser(Cursor), Translator(Translator), | 175 : NaClBitcodeParser(Cursor), Translator(Translator), |
| 178 Mod(new Module(InputName, getGlobalContext())), DL(PNaClDataLayout), | 176 Mod(new Module(InputName, getGlobalContext())), Header(Header), |
| 179 Header(Header), TypeConverter(Mod->getContext()), | 177 TypeConverter(Mod->getContext()), ErrorStatus(ErrorStatus), |
| 180 ErrorStatus(ErrorStatus), NumErrors(0), NumFunctionIds(0), | 178 NumErrors(0), NumFunctionIds(0), NumFunctionBlocks(0), |
| 181 NumFunctionBlocks(0), BlockParser(nullptr) { | 179 BlockParser(nullptr) { |
| 182 Mod->setDataLayout(PNaClDataLayout); | |
| 183 setErrStream(Translator.getContext()->getStrDump()); | 180 setErrStream(Translator.getContext()->getStrDump()); |
| 184 } | 181 } |
| 185 | 182 |
| 186 ~TopLevelParser() override {} | 183 ~TopLevelParser() override {} |
| 187 | 184 |
| 188 Ice::Translator &getTranslator() { return Translator; } | 185 Ice::Translator &getTranslator() { return Translator; } |
| 189 | 186 |
| 190 void setBlockParser(BlockParserBaseClass *NewBlockParser) { | 187 void setBlockParser(BlockParserBaseClass *NewBlockParser) { |
| 191 BlockParser = NewBlockParser; | 188 BlockParser = NewBlockParser; |
| 192 } | 189 } |
| 193 | 190 |
| 194 // Generates error with given Message. Always returns true. | 191 // Generates error with given Message. Always returns true. |
| 195 bool Error(const std::string &Message) override; | 192 bool Error(const std::string &Message) override; |
| 196 | 193 |
| 197 // Generates error message with respect to the current block parser. | 194 // Generates error message with respect to the current block parser. |
| 198 bool BlockError(const std::string &Message); | 195 bool BlockError(const std::string &Message); |
| 199 | 196 |
| 200 /// Returns the number of errors found while parsing the bitcode | 197 /// Returns the number of errors found while parsing the bitcode |
| 201 /// file. | 198 /// file. |
| 202 unsigned getNumErrors() const { return NumErrors; } | 199 unsigned getNumErrors() const { return NumErrors; } |
| 203 | 200 |
| 204 /// Returns the LLVM module associated with the translation. | 201 /// Returns the LLVM module associated with the translation. |
| 205 Module *getModule() const { return Mod.get(); } | 202 Module *getModule() const { return Mod.get(); } |
| 206 | 203 |
| 207 const DataLayout &getDataLayout() const { return DL; } | |
| 208 | |
| 209 /// Returns the number of bytes in the bitcode header. | 204 /// Returns the number of bytes in the bitcode header. |
| 210 size_t getHeaderSize() const { return Header.getHeaderSize(); } | 205 size_t getHeaderSize() const { return Header.getHeaderSize(); } |
| 211 | 206 |
| 212 /// Changes the size of the type list to the given size. | 207 /// Changes the size of the type list to the given size. |
| 213 void resizeTypeIDValues(unsigned NewSize) { TypeIDValues.resize(NewSize); } | 208 void resizeTypeIDValues(unsigned NewSize) { TypeIDValues.resize(NewSize); } |
| 214 | 209 |
| 215 /// Returns true if generation of Subzero IR is disabled. | 210 /// Returns true if generation of Subzero IR is disabled. |
| 216 bool isIRGenerationDisabled() const { | 211 bool isIRGenerationDisabled() const { |
| 217 return ALLOW_DISABLE_IR_GEN ? Translator.getFlags().DisableIRGeneration | 212 return ALLOW_DISABLE_IR_GEN ? Translator.getFlags().DisableIRGeneration |
| 218 : false; | 213 : false; |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 398 /// Returns the model for pointer types in ICE. | 393 /// Returns the model for pointer types in ICE. |
| 399 Ice::Type getIcePointerType() const { | 394 Ice::Type getIcePointerType() const { |
| 400 return TypeConverter.getIcePointerType(); | 395 return TypeConverter.getIcePointerType(); |
| 401 } | 396 } |
| 402 | 397 |
| 403 private: | 398 private: |
| 404 // The translator associated with the parser. | 399 // The translator associated with the parser. |
| 405 Ice::Translator &Translator; | 400 Ice::Translator &Translator; |
| 406 // The parsed module. | 401 // The parsed module. |
| 407 std::unique_ptr<Module> Mod; | 402 std::unique_ptr<Module> Mod; |
| 408 // The data layout to use. | |
| 409 DataLayout DL; | |
| 410 // The bitcode header. | 403 // The bitcode header. |
| 411 NaClBitcodeHeader &Header; | 404 NaClBitcodeHeader &Header; |
| 412 // Converter between LLVM and ICE types. | 405 // Converter between LLVM and ICE types. |
| 413 Ice::TypeConverter TypeConverter; | 406 Ice::TypeConverter TypeConverter; |
| 414 // The exit status that should be set to true if an error occurs. | 407 // The exit status that should be set to true if an error occurs. |
| 415 bool &ErrorStatus; | 408 bool &ErrorStatus; |
| 416 // The number of errors reported. | 409 // The number of errors reported. |
| 417 unsigned NumErrors; | 410 unsigned NumErrors; |
| 418 // The types associated with each type ID. | 411 // The types associated with each type ID. |
| 419 std::vector<ExtendedType> TypeIDValues; | 412 std::vector<ExtendedType> TypeIDValues; |
| (...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1200 // Holds operands local to the function block, based on indices | 1193 // Holds operands local to the function block, based on indices |
| 1201 // defined in the bitcode file. | 1194 // defined in the bitcode file. |
| 1202 std::vector<Ice::Operand *> LocalOperands; | 1195 std::vector<Ice::Operand *> LocalOperands; |
| 1203 // Holds the index within LocalOperands corresponding to the next | 1196 // Holds the index within LocalOperands corresponding to the next |
| 1204 // instruction that generates a value. | 1197 // instruction that generates a value. |
| 1205 uint32_t NextLocalInstIndex; | 1198 uint32_t NextLocalInstIndex; |
| 1206 // True if the last processed instruction was a terminating | 1199 // True if the last processed instruction was a terminating |
| 1207 // instruction. | 1200 // instruction. |
| 1208 bool InstIsTerminating; | 1201 bool InstIsTerminating; |
| 1209 // Upper limit of alignment power allowed by LLVM | 1202 // Upper limit of alignment power allowed by LLVM |
| 1210 static const uint64_t AlignPowerLimit = 29; | 1203 static const uint32_t AlignPowerLimit = 29; |
| 1211 | 1204 |
| 1212 void popTimerIfTimingEachFunction() const { | 1205 void popTimerIfTimingEachFunction() const { |
| 1213 if (ALLOW_DUMP && getFlags().TimeEachFunction) { | 1206 if (ALLOW_DUMP && getFlags().TimeEachFunction) { |
| 1214 getTranslator().getContext()->popTimer( | 1207 getTranslator().getContext()->popTimer( |
| 1215 getTranslator().getContext()->getTimerID( | 1208 getTranslator().getContext()->getTimerID( |
| 1216 Ice::GlobalContext::TSK_Funcs, Func->getFunctionName()), | 1209 Ice::GlobalContext::TSK_Funcs, Func->getFunctionName()), |
| 1217 Ice::GlobalContext::TSK_Funcs); | 1210 Ice::GlobalContext::TSK_Funcs); |
| 1218 } | 1211 } |
| 1219 } | 1212 } |
| 1220 | 1213 |
| 1221 // Extracts the corresponding Alignment to use, given the AlignPower | 1214 // Extracts the corresponding Alignment to use, given the AlignPower |
| 1222 // (i.e. 2**AlignPower, or 0 if AlignPower == 0). InstName is the | 1215 // (i.e. 2**AlignPower, or 0 if AlignPower == 0). InstName is the |
| 1223 // name of the instruction the alignment appears in. | 1216 // name of the instruction the alignment appears in. |
| 1224 void extractAlignment(const char *InstName, uint64_t AlignPower, | 1217 void extractAlignment(const char *InstName, uint32_t AlignPower, |
| 1225 unsigned &Alignment) { | 1218 uint32_t &Alignment) { |
| 1226 if (AlignPower <= AlignPowerLimit) { | 1219 if (AlignPower <= AlignPowerLimit) { |
| 1227 Alignment = (1 << static_cast<unsigned>(AlignPower)) >> 1; | 1220 Alignment = (1 << AlignPower) >> 1; |
| 1228 return; | 1221 return; |
| 1229 } | 1222 } |
| 1230 std::string Buffer; | 1223 std::string Buffer; |
| 1231 raw_string_ostream StrBuf(Buffer); | 1224 raw_string_ostream StrBuf(Buffer); |
| 1232 StrBuf << InstName << " alignment greater than 2**" << AlignPowerLimit | 1225 StrBuf << InstName << " alignment greater than 2**" << AlignPowerLimit |
| 1233 << ". Found: 2**" << AlignPower; | 1226 << ". Found: 2**" << AlignPower; |
| 1234 Error(StrBuf.str()); | 1227 Error(StrBuf.str()); |
| 1235 // Error recover with value that is always acceptable. | 1228 // Error recover with value that is always acceptable. |
| 1236 Alignment = 1; | 1229 Alignment = 1; |
| 1237 } | 1230 } |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1435 std::string Buffer; | 1428 std::string Buffer; |
| 1436 raw_string_ostream StrBuf(Buffer); | 1429 raw_string_ostream StrBuf(Buffer); |
| 1437 StrBuf << InstructionName << " type not allowed: " << Ty << "*"; | 1430 StrBuf << InstructionName << " type not allowed: " << Ty << "*"; |
| 1438 Error(StrBuf.str()); | 1431 Error(StrBuf.str()); |
| 1439 return false; | 1432 return false; |
| 1440 } | 1433 } |
| 1441 | 1434 |
| 1442 // Checks if loading/storing a value of type Ty is allowed for | 1435 // Checks if loading/storing a value of type Ty is allowed for |
| 1443 // the given Alignment. Otherwise generates an error message and | 1436 // the given Alignment. Otherwise generates an error message and |
| 1444 // returns false. | 1437 // returns false. |
| 1445 bool isValidLoadStoreAlignment(unsigned Alignment, Ice::Type Ty, | 1438 bool isValidLoadStoreAlignment(size_t Alignment, Ice::Type Ty, |
| 1446 const char *InstructionName) { | 1439 const char *InstructionName) { |
| 1447 if (!isValidLoadStoreType(Ty, InstructionName)) | 1440 if (!isValidLoadStoreType(Ty, InstructionName)) |
| 1448 return false; | 1441 return false; |
| 1449 if (PNaClABIProps::isAllowedAlignment(&Context->getDataLayout(), Alignment, | 1442 if (isAllowedAlignment(Alignment, Ty)) |
| 1450 Context->convertToLLVMType(Ty))) | |
| 1451 return true; | 1443 return true; |
| 1452 std::string Buffer; | 1444 std::string Buffer; |
| 1453 raw_string_ostream StrBuf(Buffer); | 1445 raw_string_ostream StrBuf(Buffer); |
| 1454 StrBuf << InstructionName << " " << Ty << "*: not allowed for alignment " | 1446 StrBuf << InstructionName << " " << Ty << "*: not allowed for alignment " |
| 1455 << Alignment; | 1447 << Alignment; |
| 1456 Error(StrBuf.str()); | 1448 Error(StrBuf.str()); |
| 1457 return false; | 1449 return false; |
| 1458 } | 1450 } |
| 1459 | 1451 |
| 1452 // Defines if the given alignment is valid for the given type. Simplified | |
| 1453 // version of PNaClABIProps::isAllowedAlignment, based on API's offered | |
| 1454 // for Ice::Type. | |
| 1455 bool isAllowedAlignment(size_t Alignment, Ice::Type Ty) const { | |
| 1456 return Alignment == typeAlignInBytes(Ty) || | |
|
jvoung (off chromium)
2014/12/09 21:32:09
I thought it was more like,
if(isScalarInteger(Ty
jvoung (off chromium)
2014/12/09 21:34:02
Ah n/m I didn't look at what typeAlignInBytes() di
| |
| 1457 (Alignment == 1 && !isVectorType(Ty)); | |
| 1458 } | |
| 1459 | |
| 1460 // Types of errors that can occur for insertelement and extractelement | 1460 // Types of errors that can occur for insertelement and extractelement |
| 1461 // instructions. | 1461 // instructions. |
| 1462 enum VectorIndexCheckValue { | 1462 enum VectorIndexCheckValue { |
| 1463 VectorIndexNotVector, | 1463 VectorIndexNotVector, |
| 1464 VectorIndexNotConstant, | 1464 VectorIndexNotConstant, |
| 1465 VectorIndexNotInRange, | 1465 VectorIndexNotInRange, |
| 1466 VectorIndexNotI32, | 1466 VectorIndexNotI32, |
| 1467 VectorIndexValid | 1467 VectorIndexValid |
| 1468 }; | 1468 }; |
| 1469 | 1469 |
| (...skipping 791 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2261 Phi->addArgument(Op, getBasicBlock(Values[i + 1])); | 2261 Phi->addArgument(Op, getBasicBlock(Values[i + 1])); |
| 2262 } | 2262 } |
| 2263 CurrentNode->appendInst(Phi); | 2263 CurrentNode->appendInst(Phi); |
| 2264 return; | 2264 return; |
| 2265 } | 2265 } |
| 2266 case naclbitc::FUNC_CODE_INST_ALLOCA: { | 2266 case naclbitc::FUNC_CODE_INST_ALLOCA: { |
| 2267 // ALLOCA: [Size, align] | 2267 // ALLOCA: [Size, align] |
| 2268 if (!isValidRecordSize(2, "alloca")) | 2268 if (!isValidRecordSize(2, "alloca")) |
| 2269 return; | 2269 return; |
| 2270 Ice::Operand *ByteCount = getRelativeOperand(Values[0], BaseIndex); | 2270 Ice::Operand *ByteCount = getRelativeOperand(Values[0], BaseIndex); |
| 2271 unsigned Alignment; | 2271 uint32_t Alignment; |
| 2272 extractAlignment("Alloca", Values[1], Alignment); | 2272 extractAlignment("Alloca", Values[1], Alignment); |
| 2273 if (isIRGenerationDisabled()) { | 2273 if (isIRGenerationDisabled()) { |
| 2274 assert(ByteCount == nullptr); | 2274 assert(ByteCount == nullptr); |
| 2275 setNextLocalInstIndex(nullptr); | 2275 setNextLocalInstIndex(nullptr); |
| 2276 return; | 2276 return; |
| 2277 } | 2277 } |
| 2278 Ice::Type PtrTy = Context->getIcePointerType(); | 2278 Ice::Type PtrTy = Context->getIcePointerType(); |
| 2279 if (ByteCount->getType() != Ice::IceType_i32) { | 2279 if (ByteCount->getType() != Ice::IceType_i32) { |
| 2280 std::string Buffer; | 2280 std::string Buffer; |
| 2281 raw_string_ostream StrBuf(Buffer); | 2281 raw_string_ostream StrBuf(Buffer); |
| 2282 StrBuf << "Alloca on non-i32 value. Found: " << *ByteCount; | 2282 StrBuf << "Alloca on non-i32 value. Found: " << *ByteCount; |
| 2283 Error(StrBuf.str()); | 2283 Error(StrBuf.str()); |
| 2284 appendErrorInstruction(PtrTy); | 2284 appendErrorInstruction(PtrTy); |
| 2285 return; | 2285 return; |
| 2286 } | 2286 } |
| 2287 CurrentNode->appendInst(Ice::InstAlloca::create(Func, ByteCount, Alignment, | 2287 CurrentNode->appendInst(Ice::InstAlloca::create(Func, ByteCount, Alignment, |
| 2288 getNextInstVar(PtrTy))); | 2288 getNextInstVar(PtrTy))); |
| 2289 return; | 2289 return; |
| 2290 } | 2290 } |
| 2291 case naclbitc::FUNC_CODE_INST_LOAD: { | 2291 case naclbitc::FUNC_CODE_INST_LOAD: { |
| 2292 // LOAD: [address, align, ty] | 2292 // LOAD: [address, align, ty] |
| 2293 if (!isValidRecordSize(3, "load")) | 2293 if (!isValidRecordSize(3, "load")) |
| 2294 return; | 2294 return; |
| 2295 Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex); | 2295 Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex); |
| 2296 Ice::Type Ty = Context->getSimpleTypeByID(Values[2]); | 2296 Ice::Type Ty = Context->getSimpleTypeByID(Values[2]); |
| 2297 unsigned Alignment; | 2297 uint32_t Alignment; |
| 2298 extractAlignment("Load", Values[1], Alignment); | 2298 extractAlignment("Load", Values[1], Alignment); |
| 2299 if (isIRGenerationDisabled()) { | 2299 if (isIRGenerationDisabled()) { |
| 2300 assert(Address == nullptr); | 2300 assert(Address == nullptr); |
| 2301 setNextLocalInstIndex(nullptr); | 2301 setNextLocalInstIndex(nullptr); |
| 2302 return; | 2302 return; |
| 2303 } | 2303 } |
| 2304 if (!isValidPointerType(Address, "Load")) { | 2304 if (!isValidPointerType(Address, "Load")) { |
| 2305 appendErrorInstruction(Ty); | 2305 appendErrorInstruction(Ty); |
| 2306 return; | 2306 return; |
| 2307 } | 2307 } |
| 2308 if (!isValidLoadStoreAlignment(Alignment, Ty, "Load")) { | 2308 if (!isValidLoadStoreAlignment(Alignment, Ty, "Load")) { |
| 2309 appendErrorInstruction(Ty); | 2309 appendErrorInstruction(Ty); |
| 2310 return; | 2310 return; |
| 2311 } | 2311 } |
| 2312 CurrentNode->appendInst( | 2312 CurrentNode->appendInst( |
| 2313 Ice::InstLoad::create(Func, getNextInstVar(Ty), Address, Alignment)); | 2313 Ice::InstLoad::create(Func, getNextInstVar(Ty), Address, Alignment)); |
| 2314 return; | 2314 return; |
| 2315 } | 2315 } |
| 2316 case naclbitc::FUNC_CODE_INST_STORE: { | 2316 case naclbitc::FUNC_CODE_INST_STORE: { |
| 2317 // STORE: [address, value, align] | 2317 // STORE: [address, value, align] |
| 2318 if (!isValidRecordSize(3, "store")) | 2318 if (!isValidRecordSize(3, "store")) |
| 2319 return; | 2319 return; |
| 2320 Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex); | 2320 Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex); |
| 2321 Ice::Operand *Value = getRelativeOperand(Values[1], BaseIndex); | 2321 Ice::Operand *Value = getRelativeOperand(Values[1], BaseIndex); |
| 2322 unsigned Alignment; | 2322 uint32_t Alignment; |
| 2323 extractAlignment("Store", Values[2], Alignment); | 2323 extractAlignment("Store", Values[2], Alignment); |
| 2324 if (isIRGenerationDisabled()) { | 2324 if (isIRGenerationDisabled()) { |
| 2325 assert(Address == nullptr && Value == nullptr); | 2325 assert(Address == nullptr && Value == nullptr); |
| 2326 return; | 2326 return; |
| 2327 } | 2327 } |
| 2328 if (!isValidPointerType(Address, "Store")) | 2328 if (!isValidPointerType(Address, "Store")) |
| 2329 return; | 2329 return; |
| 2330 if (!isValidLoadStoreAlignment(Alignment, Value->getType(), "Store")) | 2330 if (!isValidLoadStoreAlignment(Alignment, Value->getType(), "Store")) |
| 2331 return; | 2331 return; |
| 2332 CurrentNode->appendInst( | 2332 CurrentNode->appendInst( |
| (...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2942 | 2942 |
| 2943 if (TopLevelBlocks != 1) { | 2943 if (TopLevelBlocks != 1) { |
| 2944 errs() << IRFilename | 2944 errs() << IRFilename |
| 2945 << ": Contains more than one module. Found: " << TopLevelBlocks | 2945 << ": Contains more than one module. Found: " << TopLevelBlocks |
| 2946 << "\n"; | 2946 << "\n"; |
| 2947 ErrorStatus = true; | 2947 ErrorStatus = true; |
| 2948 } | 2948 } |
| 2949 } | 2949 } |
| 2950 | 2950 |
| 2951 } // end of namespace Ice | 2951 } // end of namespace Ice |
| OLD | NEW |