 Chromium Code Reviews
 Chromium Code Reviews Issue 1378163002:
  Add check to verify alignment on global variables.  (Closed) 
  Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
    
  
    Issue 1378163002:
  Add check to verify alignment on global variables.  (Closed) 
  Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master| OLD | NEW | 
|---|---|
| 1 //===- subzero/src/PNaClTranslator.cpp - ICE from bitcode -----------------===// | 1 //===- subzero/src/PNaClTranslator.cpp - ICE from bitcode -----------------===// | 
| 2 // | 2 // | 
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator | 
| 4 // | 4 // | 
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source | 
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. | 
| 7 // | 7 // | 
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// | 
| 9 /// | 9 /// | 
| 10 /// \file | 10 /// \file | 
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 345 /// ownership of the current list of global variables. Note: only returns | 345 /// ownership of the current list of global variables. Note: only returns | 
| 346 /// non-null pointer on first call. All successive calls return a null | 346 /// non-null pointer on first call. All successive calls return a null | 
| 347 /// pointer. | 347 /// pointer. | 
| 348 std::unique_ptr<Ice::VariableDeclarationList> getGlobalVariables() { | 348 std::unique_ptr<Ice::VariableDeclarationList> getGlobalVariables() { | 
| 349 // Before returning, check that ValidIDConstants has already been built. | 349 // Before returning, check that ValidIDConstants has already been built. | 
| 350 assert(!VariableDeclarations || | 350 assert(!VariableDeclarations || | 
| 351 VariableDeclarations->size() <= ValueIDConstants.size()); | 351 VariableDeclarations->size() <= ValueIDConstants.size()); | 
| 352 return std::move(VariableDeclarations); | 352 return std::move(VariableDeclarations); | 
| 353 } | 353 } | 
| 354 | 354 | 
| 355 // Upper limit of alignment power allowed by LLVM | |
| 356 static const uint32_t AlignPowerLimit = 29; | |
| 
Jim Stichnoth
2015/09/30 21:40:21
constexpr ?
 
Karl
2015/09/30 22:23:45
Done.
 | |
| 357 | |
| 358 // Extracts the corresponding Alignment to use, given the AlignPower (i.e. | |
| 359 // 2**(AlignPower-1), or 0 if AlignPower == 0). Parser defines the block | |
| 360 // context the alignment check appears in, and Prefix defines the context the | |
| 361 // alignment appears in. | |
| 362 void extractAlignment(NaClBitcodeParser *Parser, const char *Prefix, | |
| 
Jim Stichnoth
2015/09/30 21:40:21
Can this function directly return Alignment instea
 
Karl
2015/09/30 22:23:45
Done.
 | |
| 363 uint32_t AlignPower, uint32_t &Alignment) { | |
| 364 if (AlignPower <= AlignPowerLimit + 1) { | |
| 365 Alignment = (1 << AlignPower) >> 1; | |
| 366 return; | |
| 367 } | |
| 368 std::string Buffer; | |
| 369 raw_string_ostream StrBuf(Buffer); | |
| 370 StrBuf << Prefix << " alignment greater than 2**" << AlignPowerLimit | |
| 371 << ". Found: 2**" << (AlignPower - 1); | |
| 372 Parser->Error(StrBuf.str()); | |
| 373 // Error recover with value that is always acceptable. | |
| 374 Alignment = 1; | |
| 375 } | |
| 376 | |
| 355 private: | 377 private: | 
| 356 // The translator associated with the parser. | 378 // The translator associated with the parser. | 
| 357 Ice::Translator &Translator; | 379 Ice::Translator &Translator; | 
| 358 // The exit status that should be set to true if an error occurs. | 380 // The exit status that should be set to true if an error occurs. | 
| 359 Ice::ErrorCode &ErrorStatus; | 381 Ice::ErrorCode &ErrorStatus; | 
| 360 // The number of errors reported. | 382 // The number of errors reported. | 
| 361 unsigned NumErrors = 0; | 383 unsigned NumErrors = 0; | 
| 362 // The types associated with each type ID. | 384 // The types associated with each type ID. | 
| 363 std::vector<ExtendedType> TypeIDValues; | 385 std::vector<ExtendedType> TypeIDValues; | 
| 364 // The set of functions (prototype and defined). | 386 // The set of functions (prototype and defined). | 
| (...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1054 SpecifiedNumberVars = Values[0]; | 1076 SpecifiedNumberVars = Values[0]; | 
| 1055 return; | 1077 return; | 
| 1056 case naclbitc::GLOBALVAR_VAR: { | 1078 case naclbitc::GLOBALVAR_VAR: { | 
| 1057 // VAR: [align, isconst] | 1079 // VAR: [align, isconst] | 
| 1058 if (!isValidRecordSize(2, "variable")) | 1080 if (!isValidRecordSize(2, "variable")) | 
| 1059 return; | 1081 return; | 
| 1060 verifyNoMissingInitializers(); | 1082 verifyNoMissingInitializers(); | 
| 1061 // Always build the global variable, even if IR generation is turned off. | 1083 // Always build the global variable, even if IR generation is turned off. | 
| 1062 // This is needed because we need a placeholder in the top-level context | 1084 // This is needed because we need a placeholder in the top-level context | 
| 1063 // when no IR is generated. | 1085 // when no IR is generated. | 
| 1086 uint32_t Alignment; | |
| 1087 Context->extractAlignment(this, "Global variable", Values[0], Alignment); | |
| 1064 CurGlobalVar = getGlobalVarByID(NextGlobalID); | 1088 CurGlobalVar = getGlobalVarByID(NextGlobalID); | 
| 1065 if (!isIRGenerationDisabled()) { | 1089 if (!isIRGenerationDisabled()) { | 
| 1066 InitializersNeeded = 1; | 1090 InitializersNeeded = 1; | 
| 1067 CurGlobalVar->setAlignment((1 << Values[0]) >> 1); | 1091 CurGlobalVar->setAlignment(Alignment); | 
| 1068 CurGlobalVar->setIsConstant(Values[1] != 0); | 1092 CurGlobalVar->setIsConstant(Values[1] != 0); | 
| 1069 } | 1093 } | 
| 1070 ++NextGlobalID; | 1094 ++NextGlobalID; | 
| 1071 return; | 1095 return; | 
| 1072 } | 1096 } | 
| 1073 case naclbitc::GLOBALVAR_COMPOUND: | 1097 case naclbitc::GLOBALVAR_COMPOUND: | 
| 1074 // COMPOUND: [size] | 1098 // COMPOUND: [size] | 
| 1075 if (!isValidRecordSize(1, "compound")) | 1099 if (!isValidRecordSize(1, "compound")) | 
| 1076 return; | 1100 return; | 
| 1077 if (!CurGlobalVar->getInitializers().empty()) { | 1101 if (!CurGlobalVar->getInitializers().empty()) { | 
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1374 // Holds the dividing point between local and global absolute value indices. | 1398 // Holds the dividing point between local and global absolute value indices. | 
| 1375 size_t CachedNumGlobalValueIDs; | 1399 size_t CachedNumGlobalValueIDs; | 
| 1376 // Holds operands local to the function block, based on indices defined in | 1400 // Holds operands local to the function block, based on indices defined in | 
| 1377 // the bitcode file. | 1401 // the bitcode file. | 
| 1378 Ice::OperandList LocalOperands; | 1402 Ice::OperandList LocalOperands; | 
| 1379 // Holds the index within LocalOperands corresponding to the next instruction | 1403 // Holds the index within LocalOperands corresponding to the next instruction | 
| 1380 // that generates a value. | 1404 // that generates a value. | 
| 1381 NaClBcIndexSize_t NextLocalInstIndex; | 1405 NaClBcIndexSize_t NextLocalInstIndex; | 
| 1382 // True if the last processed instruction was a terminating instruction. | 1406 // True if the last processed instruction was a terminating instruction. | 
| 1383 bool InstIsTerminating = false; | 1407 bool InstIsTerminating = false; | 
| 1384 // Upper limit of alignment power allowed by LLVM | |
| 1385 static const uint32_t AlignPowerLimit = 29; | |
| 1386 | |
| 1387 // Extracts the corresponding Alignment to use, given the AlignPower (i.e. | |
| 1388 // 2**(AlignPower-1), or 0 if AlignPower == 0). InstName is the name of the | |
| 1389 // instruction the alignment appears in. | |
| 1390 void extractAlignment(const char *InstName, uint32_t AlignPower, | |
| 1391 uint32_t &Alignment) { | |
| 1392 if (AlignPower <= AlignPowerLimit + 1) { | |
| 1393 Alignment = (1 << AlignPower) >> 1; | |
| 1394 return; | |
| 1395 } | |
| 1396 std::string Buffer; | |
| 1397 raw_string_ostream StrBuf(Buffer); | |
| 1398 StrBuf << InstName << " alignment greater than 2**" << AlignPowerLimit | |
| 1399 << ". Found: 2**" << (AlignPower - 1); | |
| 1400 Error(StrBuf.str()); | |
| 1401 // Error recover with value that is always acceptable. | |
| 1402 Alignment = 1; | |
| 1403 } | |
| 1404 | 1408 | 
| 1405 bool ParseBlock(unsigned BlockID) override; | 1409 bool ParseBlock(unsigned BlockID) override; | 
| 1406 | 1410 | 
| 1407 void ProcessRecord() override; | 1411 void ProcessRecord() override; | 
| 1408 | 1412 | 
| 1409 void EnterBlock(unsigned NumWords) final { | 1413 void EnterBlock(unsigned NumWords) final { | 
| 1410 // Note: Bitstream defines words as 32-bit values. | 1414 // Note: Bitstream defines words as 32-bit values. | 
| 1411 NumBytesDefiningFunction = NumWords * sizeof(uint32_t); | 1415 NumBytesDefiningFunction = NumWords * sizeof(uint32_t); | 
| 1412 // We know that all records are minimally defined by a two-bit abreviation. | 1416 // We know that all records are minimally defined by a two-bit abreviation. | 
| 1413 MaxRecordsInBlock = NumBytesDefiningFunction * (CHAR_BIT >> 1); | 1417 MaxRecordsInBlock = NumBytesDefiningFunction * (CHAR_BIT >> 1); | 
| (...skipping 1172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2586 } | 2590 } | 
| 2587 CurrentNode->appendInst(Phi); | 2591 CurrentNode->appendInst(Phi); | 
| 2588 return; | 2592 return; | 
| 2589 } | 2593 } | 
| 2590 case naclbitc::FUNC_CODE_INST_ALLOCA: { | 2594 case naclbitc::FUNC_CODE_INST_ALLOCA: { | 
| 2591 // ALLOCA: [Size, align] | 2595 // ALLOCA: [Size, align] | 
| 2592 if (!isValidRecordSize(2, "alloca")) | 2596 if (!isValidRecordSize(2, "alloca")) | 
| 2593 return; | 2597 return; | 
| 2594 Ice::Operand *ByteCount = getRelativeOperand(Values[0], BaseIndex); | 2598 Ice::Operand *ByteCount = getRelativeOperand(Values[0], BaseIndex); | 
| 2595 uint32_t Alignment; | 2599 uint32_t Alignment; | 
| 2596 extractAlignment("Alloca", Values[1], Alignment); | 2600 Context->extractAlignment(this, "Alloca", Values[1], Alignment); | 
| 2597 if (isIRGenerationDisabled()) { | 2601 if (isIRGenerationDisabled()) { | 
| 2598 assert(ByteCount == nullptr); | 2602 assert(ByteCount == nullptr); | 
| 2599 setNextLocalInstIndex(nullptr); | 2603 setNextLocalInstIndex(nullptr); | 
| 2600 return; | 2604 return; | 
| 2601 } | 2605 } | 
| 2602 Ice::Type PtrTy = Ice::getPointerType(); | 2606 Ice::Type PtrTy = Ice::getPointerType(); | 
| 2603 if (ByteCount->getType() != Ice::IceType_i32) { | 2607 if (ByteCount->getType() != Ice::IceType_i32) { | 
| 2604 std::string Buffer; | 2608 std::string Buffer; | 
| 2605 raw_string_ostream StrBuf(Buffer); | 2609 raw_string_ostream StrBuf(Buffer); | 
| 2606 StrBuf << "Alloca on non-i32 value. Found: " << *ByteCount; | 2610 StrBuf << "Alloca on non-i32 value. Found: " << *ByteCount; | 
| 2607 Error(StrBuf.str()); | 2611 Error(StrBuf.str()); | 
| 2608 appendErrorInstruction(PtrTy); | 2612 appendErrorInstruction(PtrTy); | 
| 2609 return; | 2613 return; | 
| 2610 } | 2614 } | 
| 2611 CurrentNode->appendInst(Ice::InstAlloca::create( | 2615 CurrentNode->appendInst(Ice::InstAlloca::create( | 
| 2612 Func.get(), ByteCount, Alignment, getNextInstVar(PtrTy))); | 2616 Func.get(), ByteCount, Alignment, getNextInstVar(PtrTy))); | 
| 2613 return; | 2617 return; | 
| 2614 } | 2618 } | 
| 2615 case naclbitc::FUNC_CODE_INST_LOAD: { | 2619 case naclbitc::FUNC_CODE_INST_LOAD: { | 
| 2616 // LOAD: [address, align, ty] | 2620 // LOAD: [address, align, ty] | 
| 2617 if (!isValidRecordSize(3, "load")) | 2621 if (!isValidRecordSize(3, "load")) | 
| 2618 return; | 2622 return; | 
| 2619 Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex); | 2623 Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex); | 
| 2620 Ice::Type Ty = Context->getSimpleTypeByID(Values[2]); | 2624 Ice::Type Ty = Context->getSimpleTypeByID(Values[2]); | 
| 2621 uint32_t Alignment; | 2625 uint32_t Alignment; | 
| 2622 extractAlignment("Load", Values[1], Alignment); | 2626 Context->extractAlignment(this, "Load", Values[1], Alignment); | 
| 2623 if (isIRGenerationDisabled()) { | 2627 if (isIRGenerationDisabled()) { | 
| 2624 assert(Address == nullptr); | 2628 assert(Address == nullptr); | 
| 2625 setNextLocalInstIndex(nullptr); | 2629 setNextLocalInstIndex(nullptr); | 
| 2626 return; | 2630 return; | 
| 2627 } | 2631 } | 
| 2628 if (!isValidPointerType(Address, "Load")) { | 2632 if (!isValidPointerType(Address, "Load")) { | 
| 2629 appendErrorInstruction(Ty); | 2633 appendErrorInstruction(Ty); | 
| 2630 return; | 2634 return; | 
| 2631 } | 2635 } | 
| 2632 if (!isValidLoadStoreAlignment(Alignment, Ty, "Load")) { | 2636 if (!isValidLoadStoreAlignment(Alignment, Ty, "Load")) { | 
| 2633 appendErrorInstruction(Ty); | 2637 appendErrorInstruction(Ty); | 
| 2634 return; | 2638 return; | 
| 2635 } | 2639 } | 
| 2636 CurrentNode->appendInst(Ice::InstLoad::create( | 2640 CurrentNode->appendInst(Ice::InstLoad::create( | 
| 2637 Func.get(), getNextInstVar(Ty), Address, Alignment)); | 2641 Func.get(), getNextInstVar(Ty), Address, Alignment)); | 
| 2638 return; | 2642 return; | 
| 2639 } | 2643 } | 
| 2640 case naclbitc::FUNC_CODE_INST_STORE: { | 2644 case naclbitc::FUNC_CODE_INST_STORE: { | 
| 2641 // STORE: [address, value, align] | 2645 // STORE: [address, value, align] | 
| 2642 if (!isValidRecordSize(3, "store")) | 2646 if (!isValidRecordSize(3, "store")) | 
| 2643 return; | 2647 return; | 
| 2644 Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex); | 2648 Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex); | 
| 2645 Ice::Operand *Value = getRelativeOperand(Values[1], BaseIndex); | 2649 Ice::Operand *Value = getRelativeOperand(Values[1], BaseIndex); | 
| 2646 uint32_t Alignment; | 2650 uint32_t Alignment; | 
| 2647 extractAlignment("Store", Values[2], Alignment); | 2651 Context->extractAlignment(this, "Store", Values[2], Alignment); | 
| 2648 if (isIRGenerationDisabled()) { | 2652 if (isIRGenerationDisabled()) { | 
| 2649 assert(Address == nullptr && Value == nullptr); | 2653 assert(Address == nullptr && Value == nullptr); | 
| 2650 return; | 2654 return; | 
| 2651 } | 2655 } | 
| 2652 if (!isValidPointerType(Address, "Store")) | 2656 if (!isValidPointerType(Address, "Store")) | 
| 2653 return; | 2657 return; | 
| 2654 if (!isValidLoadStoreAlignment(Alignment, Value->getType(), "Store")) | 2658 if (!isValidLoadStoreAlignment(Alignment, Value->getType(), "Store")) | 
| 2655 return; | 2659 return; | 
| 2656 CurrentNode->appendInst( | 2660 CurrentNode->appendInst( | 
| 2657 Ice::InstStore::create(Func.get(), Value, Address, Alignment)); | 2661 Ice::InstStore::create(Func.get(), Value, Address, Alignment)); | 
| (...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3282 raw_string_ostream StrBuf(Buffer); | 3286 raw_string_ostream StrBuf(Buffer); | 
| 3283 StrBuf << IRFilename << ": Does not contain a module!"; | 3287 StrBuf << IRFilename << ": Does not contain a module!"; | 
| 3284 llvm::report_fatal_error(StrBuf.str()); | 3288 llvm::report_fatal_error(StrBuf.str()); | 
| 3285 } | 3289 } | 
| 3286 if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) { | 3290 if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) { | 
| 3287 llvm::report_fatal_error("Bitcode stream should be a multiple of 4 bytes"); | 3291 llvm::report_fatal_error("Bitcode stream should be a multiple of 4 bytes"); | 
| 3288 } | 3292 } | 
| 3289 } | 3293 } | 
| 3290 | 3294 | 
| 3291 } // end of namespace Ice | 3295 } // end of namespace Ice | 
| OLD | NEW |