Commit aa0ce790 by Karl Schimpf

Fix processing of global variable indices in the global vars block.

The code used to use a vector to hold global variables associated with indices. The problem was that the count record in the global vars block would generate variables for the given count (even if very large). To fix this, we created a local unordered map to associate indices with defined/referenced globals. After processing the global vars block, this unordered map is used to verify the size makes sense, and then install the recognized global variables into the (top-level) contents. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4257 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1278793006 .
parent 9df4a379
...@@ -306,24 +306,11 @@ public: ...@@ -306,24 +306,11 @@ public:
} }
} }
/// Creates Count global variable declarations. /// Adds the given global declaration to the end of the list of global
void createGlobalVariables(NaClBcIndexSize_t Count) { /// declarations.
void addGlobalDeclaration(Ice::VariableDeclaration *Decl) {
assert(VariableDeclarations); assert(VariableDeclarations);
assert(VariableDeclarations->empty()); VariableDeclarations->push_back(Decl);
for (size_t i = 0; i < Count; ++i) {
VariableDeclarations->push_back(
Ice::VariableDeclaration::create(getTranslator().getContext()));
}
}
/// Returns the number of global variable declarations in the
/// bitcode file.
size_t getNumGlobalVariables() const {
if (VariableDeclarations) {
return VariableDeclarations->size();
} else {
return ValueIDConstants.size() - FunctionDeclarationList.size();
}
} }
/// Returns the global variable declaration with the given index. /// Returns the global variable declaration with the given index.
...@@ -955,6 +942,7 @@ public: ...@@ -955,6 +942,7 @@ public:
GlobalsParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser) GlobalsParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
: BlockParserBaseClass(BlockID, EnclosingParser), : BlockParserBaseClass(BlockID, EnclosingParser),
Timer(Ice::TimerStack::TT_parseGlobals, getTranslator().getContext()), Timer(Ice::TimerStack::TT_parseGlobals, getTranslator().getContext()),
NumFunctionIDs(Context->getNumFunctionIDs()),
DummyGlobalVar( DummyGlobalVar(
Ice::VariableDeclaration::create(getTranslator().getContext())), Ice::VariableDeclaration::create(getTranslator().getContext())),
CurGlobalVar(DummyGlobalVar) {} CurGlobalVar(DummyGlobalVar) {}
...@@ -964,7 +952,21 @@ public: ...@@ -964,7 +952,21 @@ public:
const char *getBlockName() const override { return "globals"; } const char *getBlockName() const override { return "globals"; }
private: private:
typedef std::unordered_map<NaClBcIndexSize_t, Ice::VariableDeclaration *>
GlobalVarsMapType;
Ice::TimerMarker Timer; Ice::TimerMarker Timer;
// Holds global variables generated/referenced in the global variables block.
GlobalVarsMapType GlobalVarsMap;
// Holds the number of defined function IDs.
NaClBcIndexSize_t NumFunctionIDs;
// Holds the specified number of global variables by the count record in
// the global variables block.
NaClBcIndexSize_t SpecifiedNumberVars = 0;
// Keeps track of how many initializers are expected for the global variable // Keeps track of how many initializers are expected for the global variable
// declaration being built. // declaration being built.
NaClBcIndexSize_t InitializersNeeded = 0; NaClBcIndexSize_t InitializersNeeded = 0;
...@@ -980,16 +982,43 @@ private: ...@@ -980,16 +982,43 @@ private:
// Holds the current global variable declaration being built. // Holds the current global variable declaration being built.
Ice::VariableDeclaration *CurGlobalVar; Ice::VariableDeclaration *CurGlobalVar;
void ExitBlock() override { // Returns the global variable associated with the given Index.
verifyNoMissingInitializers(); Ice::VariableDeclaration *getGlobalVarByID(NaClBcIndexSize_t Index) {
unsigned NumIDs = Context->getNumGlobalVariables(); Ice::VariableDeclaration *&Decl = GlobalVarsMap[Index];
if (NextGlobalID < NumIDs) { if (Decl == nullptr)
Decl = Ice::VariableDeclaration::create(getTranslator().getContext());
return Decl;
}
// Returns the global declaration associated with the given index.
Ice::GlobalDeclaration *getGlobalDeclByID(NaClBcIndexSize_t Index) {
if (Index < NumFunctionIDs)
return Context->getFunctionByID(Index);
return getGlobalVarByID(Index - NumFunctionIDs);
}
// If global variables parsed correctly, install them into the top-level
// context.
void installGlobalVariables() {
// Verify specified number of globals matches number found.
size_t NumGlobals = GlobalVarsMap.size();
if (SpecifiedNumberVars != NumGlobals ||
SpecifiedNumberVars != NextGlobalID) {
std::string Buffer; std::string Buffer;
raw_string_ostream StrBuf(Buffer); raw_string_ostream StrBuf(Buffer);
StrBuf << getBlockName() << " block expects " << NumIDs StrBuf << getBlockName() << " block expects " << SpecifiedNumberVars
<< " global variable declarations. Found: " << NextGlobalID; << " global variables. Found: " << GlobalVarsMap.size();
Error(StrBuf.str()); Error(StrBuf.str());
return;
} }
// Install global variables into top-level context.
for (size_t I = 0; I < NumGlobals; ++I)
Context->addGlobalDeclaration(GlobalVarsMap[I]);
}
void ExitBlock() override {
verifyNoMissingInitializers();
installGlobalVariables();
BlockParserBaseClass::ExitBlock(); BlockParserBaseClass::ExitBlock();
} }
...@@ -1022,20 +1051,23 @@ void GlobalsParser::ProcessRecord() { ...@@ -1022,20 +1051,23 @@ void GlobalsParser::ProcessRecord() {
// COUNT: [n] // COUNT: [n]
if (!isValidRecordSize(1, "count")) if (!isValidRecordSize(1, "count"))
return; return;
if (NextGlobalID != Context->getNumGlobalVariables()) { if (SpecifiedNumberVars || NextGlobalID) {
Error("Globals count record not first in block."); Error("Globals count record not first in block.");
return; return;
} }
Context->createGlobalVariables(Values[0]); SpecifiedNumberVars = Values[0];
return; return;
case naclbitc::GLOBALVAR_VAR: { case naclbitc::GLOBALVAR_VAR: {
// VAR: [align, isconst] // VAR: [align, isconst]
if (!isValidRecordSize(2, "variable")) if (!isValidRecordSize(2, "variable"))
return; return;
verifyNoMissingInitializers(); verifyNoMissingInitializers();
// Always build the global variable, even if IR generation is turned off.
// This is needed because we need a placeholder in the top-level context
// when no IR is generated.
CurGlobalVar = getGlobalVarByID(NextGlobalID);
if (!isIRGenerationDisabled()) { if (!isIRGenerationDisabled()) {
InitializersNeeded = 1; InitializersNeeded = 1;
CurGlobalVar = Context->getGlobalVariableByID(NextGlobalID);
CurGlobalVar->setAlignment((1 << Values[0]) >> 1); CurGlobalVar->setAlignment((1 << Values[0]) >> 1);
CurGlobalVar->setIsConstant(Values[1] != 0); CurGlobalVar->setIsConstant(Values[1] != 0);
} }
...@@ -1088,7 +1120,15 @@ void GlobalsParser::ProcessRecord() { ...@@ -1088,7 +1120,15 @@ void GlobalsParser::ProcessRecord() {
return; return;
if (isIRGenerationDisabled()) if (isIRGenerationDisabled())
return; return;
unsigned Index = Values[0]; NaClBcIndexSize_t Index = Values[0];
NaClBcIndexSize_t IndexLimit = SpecifiedNumberVars + NumFunctionIDs;
if (Index >= IndexLimit) {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Relocation index " << Index << " to big. Expect index < "
<< IndexLimit;
Error(StrBuf.str());
}
uint64_t Offset = 0; uint64_t Offset = 0;
if (Values.size() == 2) { if (Values.size() == 2) {
Offset = Values[1]; Offset = Values[1];
...@@ -1101,7 +1141,7 @@ void GlobalsParser::ProcessRecord() { ...@@ -1101,7 +1141,7 @@ void GlobalsParser::ProcessRecord() {
} }
CurGlobalVar->addInitializer( CurGlobalVar->addInitializer(
Ice::VariableDeclaration::RelocInitializer::create( Ice::VariableDeclaration::RelocInitializer::create(
Context->getGlobalDeclarationByID(Index), Offset)); getGlobalDeclByID(Index), Offset));
return; return;
} }
default: default:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment