Commit 6ca7d2b6 by Karl Schimpf

Fix PNaCl bitcode reader to release global variables to emitter.

Fixes the PNaCl bitcode reader to maintain two lists of global variables. The first, VariableDeclarations, is the list of variable declarations to be lowered by the emitter. The second, ValueIDConstants, is the corresponding constant symbol to use when references to the corresponding global variable declaration is referenced when processing functions. BUG=None R=jvoung@chromium.org, stichnot@chromium.org Review URL: https://codereview.chromium.org/883673005
parent df80eb86
...@@ -163,11 +163,12 @@ public: ...@@ -163,11 +163,12 @@ public:
NaClBitstreamCursor &Cursor, Ice::ErrorCode &ErrorStatus) NaClBitstreamCursor &Cursor, Ice::ErrorCode &ErrorStatus)
: NaClBitcodeParser(Cursor), Translator(Translator), Header(Header), : NaClBitcodeParser(Cursor), Translator(Translator), Header(Header),
ErrorStatus(ErrorStatus), NumErrors(0), NextDefiningFunctionID(0), ErrorStatus(ErrorStatus), NumErrors(0), NextDefiningFunctionID(0),
VariableDeclarations(new Ice::VariableDeclarationList()),
BlockParser(nullptr), StubbedConstCallValue(nullptr) {} BlockParser(nullptr), StubbedConstCallValue(nullptr) {}
~TopLevelParser() override {} ~TopLevelParser() override {}
Ice::Translator &getTranslator() { return Translator; } Ice::Translator &getTranslator() const { return Translator; }
void setBlockParser(BlockParserBaseClass *NewBlockParser) { void setBlockParser(BlockParserBaseClass *NewBlockParser) {
BlockParser = NewBlockParser; BlockParser = NewBlockParser;
...@@ -251,71 +252,27 @@ public: ...@@ -251,71 +252,27 @@ public:
return reportGetFunctionByIDError(ID); return reportGetFunctionByIDError(ID);
} }
/// Returns the list of function declarations. /// Returns the constant associated with the given global value ID.
const FunctionDeclarationListType &getFunctionDeclarationList() const { Ice::Constant *getGlobalConstantByID(unsigned ID) {
return FunctionDeclarationList; assert(ID < ValueIDConstants.size());
return ValueIDConstants[ID];
} }
/// Returns the corresponding constant associated with a global declaration. /// Install names for all global values without names. Called after
/// (i.e. relocatable). /// the global value symbol table is processed, but before any
Ice::Constant *getOrCreateGlobalConstantByID(unsigned ID) { /// function blocks are processed.
// TODO(kschimpf): Can this be built when creating global initializers? void installGlobalNames() {
Ice::Constant *C; assert(VariableDeclarations);
if (ID >= ValueIDConstants.size()) { installGlobalVarNames();
C = nullptr; installFunctionNames();
unsigned ExpectedSize = }
FunctionDeclarationList.size() + VariableDeclarations.size();
if (ID >= ExpectedSize)
ExpectedSize = ID;
ValueIDConstants.resize(ExpectedSize);
} else {
C = ValueIDConstants[ID];
}
if (C != nullptr)
return C;
if (isIRGenerationDisabled()) { void createValueIDs() {
ValueIDConstants[ID] = nullptr; assert(VariableDeclarations);
return nullptr; ValueIDConstants.reserve(VariableDeclarations->size() +
} FunctionDeclarationList.size());
createValueIDsForFunctions();
// If reached, no such constant exists, create one. createValueIDsForGlobalVars();
// TODO(kschimpf) Don't get addresses of intrinsic function declarations.
Ice::GlobalDeclaration *Decl = nullptr;
unsigned FcnIDSize = FunctionDeclarationList.size();
bool IsUndefined = false;
if (ID < FcnIDSize) {
Decl = FunctionDeclarationList[ID];
const auto Func = llvm::cast<Ice::FunctionDeclaration>(Decl);
IsUndefined = Func->isProto();
} else if ((ID - FcnIDSize) < VariableDeclarations.size()) {
Decl = VariableDeclarations[ID - FcnIDSize];
const auto Var = llvm::cast<Ice::VariableDeclaration>(Decl);
IsUndefined = !Var->hasInitializer();
}
Ice::IceString Name;
bool SuppressMangling;
if (Decl) {
Name = Decl->getName();
SuppressMangling = Decl->getSuppressMangling();
} else {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Reference to global not defined: " << ID;
BlockError(StrBuf.str());
// TODO(kschimpf) Remove error recovery once implementation complete.
Name = "??";
SuppressMangling = false;
}
if (IsUndefined)
C = getTranslator().getContext()->getConstantExternSym(Name);
else {
const Ice::RelocOffsetT Offset = 0;
C = getTranslator().getContext()->getConstantSym(Offset, Name,
SuppressMangling);
}
ValueIDConstants[ID] = C;
return C;
} }
/// Returns a defined function reference to be used in place of /// Returns a defined function reference to be used in place of
...@@ -328,7 +285,7 @@ public: ...@@ -328,7 +285,7 @@ public:
for (unsigned i = 0; i < getNumFunctionIDs(); ++i) { for (unsigned i = 0; i < getNumFunctionIDs(); ++i) {
Ice::FunctionDeclaration *Func = getFunctionByID(i); Ice::FunctionDeclaration *Func = getFunctionByID(i);
if (!Func->isProto()) { if (!Func->isProto()) {
StubbedConstCallValue = getOrCreateGlobalConstantByID(i); StubbedConstCallValue = getGlobalConstantByID(i);
return StubbedConstCallValue; return StubbedConstCallValue;
} }
} }
...@@ -342,27 +299,37 @@ public: ...@@ -342,27 +299,37 @@ public:
/// Returns the number of global declarations (i.e. IDs) defined in /// Returns the number of global declarations (i.e. IDs) defined in
/// the bitcode file. /// the bitcode file.
unsigned getNumGlobalIDs() const { unsigned getNumGlobalIDs() const {
return FunctionDeclarationList.size() + VariableDeclarations.size(); if (VariableDeclarations) {
return FunctionDeclarationList.size() + VariableDeclarations->size();
} else {
return ValueIDConstants.size();
}
} }
/// Creates Count global variable declarations. /// Creates Count global variable declarations.
void CreateGlobalVariables(size_t Count) { void CreateGlobalVariables(size_t Count) {
assert(VariableDeclarations.empty()); assert(VariableDeclarations);
assert(VariableDeclarations->empty());
for (size_t i = 0; i < Count; ++i) { for (size_t i = 0; i < Count; ++i) {
VariableDeclarations.push_back(Ice::VariableDeclaration::create()); VariableDeclarations->push_back(Ice::VariableDeclaration::create());
} }
} }
/// Returns the number of global variable declarations in the /// Returns the number of global variable declarations in the
/// bitcode file. /// bitcode file.
Ice::SizeT getNumGlobalVariables() const { Ice::SizeT getNumGlobalVariables() const {
return VariableDeclarations.size(); 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.
Ice::VariableDeclaration *getGlobalVariableByID(unsigned Index) { Ice::VariableDeclaration *getGlobalVariableByID(unsigned Index) {
if (Index < VariableDeclarations.size()) assert(VariableDeclarations);
return VariableDeclarations[Index]; if (Index < VariableDeclarations->size())
return VariableDeclarations->at(Index);
return reportGetGlobalVariableByIDError(Index); return reportGetGlobalVariableByIDError(Index);
} }
...@@ -376,9 +343,16 @@ public: ...@@ -376,9 +343,16 @@ public:
return getGlobalVariableByID(Index - NumFunctionIds); return getGlobalVariableByID(Index - NumFunctionIds);
} }
/// Returns the list of parsed global variable declarations. /// Returns the list of parsed global variable
const Ice::VariableDeclarationList &getGlobalVariables() { /// declarations. Releases ownership of the current list of global
return VariableDeclarations; /// variables. Note: only returns non-null pointer on first
/// call. All successive calls return a null pointer.
std::unique_ptr<Ice::VariableDeclarationList> getGlobalVariables() {
// Before returning, check that ValidIDConstants has already been
// built.
assert(!VariableDeclarations ||
VariableDeclarations->size() <= ValueIDConstants.size());
return std::move(VariableDeclarations);
} }
private: private:
...@@ -402,7 +376,7 @@ private: ...@@ -402,7 +376,7 @@ private:
// actually-defined function. // actually-defined function.
size_t NextDefiningFunctionID; size_t NextDefiningFunctionID;
// The set of global variables. // The set of global variables.
Ice::VariableDeclarationList VariableDeclarations; std::unique_ptr<Ice::VariableDeclarationList> VariableDeclarations;
// Relocatable constants associated with global declarations. // Relocatable constants associated with global declarations.
std::vector<Ice::Constant *> ValueIDConstants; std::vector<Ice::Constant *> ValueIDConstants;
// Error recovery value to use when getFuncSigTypeByID fails. // Error recovery value to use when getFuncSigTypeByID fails.
...@@ -432,6 +406,85 @@ private: ...@@ -432,6 +406,85 @@ private:
return nullptr; return nullptr;
} }
// Gives Decl a name if it doesn't already have one. Prefix and
// NameIndex are used to generate the name. NameIndex is
// automatically incremented if a new name is created. DeclType is
// literal text describing the type of name being created. Also
// generates warning if created names may conflict with named
// declarations.
void installDeclarationName(Ice::GlobalDeclaration *Decl,
const Ice::IceString &Prefix,
const char *DeclType, uint32_t &NameIndex) {
if (Decl->hasName()) {
Translator.checkIfUnnamedNameSafe(Decl->getName(), DeclType, Prefix);
} else {
Decl->setName(Translator.createUnnamedName(Prefix, NameIndex));
++NameIndex;
}
}
// Installs names for global variables without names.
void installGlobalVarNames() {
assert(VariableDeclarations);
const Ice::IceString &GlobalPrefix =
getTranslator().getFlags().getDefaultGlobalPrefix();
if (!GlobalPrefix.empty()) {
uint32_t NameIndex = 0;
for (Ice::VariableDeclaration *Var : *VariableDeclarations) {
installDeclarationName(Var, GlobalPrefix, "global", NameIndex);
}
}
}
// Installs names for functions without names.
void installFunctionNames() {
const Ice::IceString &FunctionPrefix =
getTranslator().getFlags().getDefaultFunctionPrefix();
if (!FunctionPrefix.empty()) {
uint32_t NameIndex = 0;
for (Ice::FunctionDeclaration *Func : FunctionDeclarationList) {
installDeclarationName(Func, FunctionPrefix, "function", NameIndex);
}
}
}
// Builds a constant symbol named Name, suppressing name mangling if
// SuppressMangling. IsExternal is true iff the symbol is external.
Ice::Constant *getConstantSym(const Ice::IceString &Name,
bool SuppressMangling, bool IsExternal) const {
if (IsExternal) {
return getTranslator().getContext()->getConstantExternSym(Name);
} else {
const Ice::RelocOffsetT Offset = 0;
return getTranslator().getContext()->getConstantSym(Offset, Name,
SuppressMangling);
}
}
// Converts function declarations into constant value IDs.
void createValueIDsForFunctions() {
for (const Ice::FunctionDeclaration *Func : FunctionDeclarationList) {
Ice::Constant *C = nullptr;
if (!isIRGenerationDisabled()) {
C = getConstantSym(Func->getName(), Func->getSuppressMangling(),
Func->isProto());
}
ValueIDConstants.push_back(C);
}
}
// Converts global variable declarations into constant value IDs.
void createValueIDsForGlobalVars() {
for (const Ice::VariableDeclaration *Decl : *VariableDeclarations) {
Ice::Constant *C = nullptr;
if (!isIRGenerationDisabled()) {
C = getConstantSym(Decl->getName(), Decl->getSuppressMangling(),
!Decl->hasInitializer());
}
ValueIDConstants.push_back(C);
}
}
// Reports that type ID is undefined, or not of the WantedType. // Reports that type ID is undefined, or not of the WantedType.
void reportBadTypeIDAs(unsigned ID, const ExtendedType *Ty, void reportBadTypeIDAs(unsigned ID, const ExtendedType *Ty,
ExtendedType::TypeKind WantedType); ExtendedType::TypeKind WantedType);
...@@ -494,11 +547,11 @@ TopLevelParser::reportGetGlobalVariableByIDError(unsigned Index) { ...@@ -494,11 +547,11 @@ TopLevelParser::reportGetGlobalVariableByIDError(unsigned Index) {
raw_string_ostream StrBuf(Buffer); raw_string_ostream StrBuf(Buffer);
StrBuf << "Global index " << Index StrBuf << "Global index " << Index
<< " not allowed. Out of range. Must be less than " << " not allowed. Out of range. Must be less than "
<< VariableDeclarations.size(); << VariableDeclarations->size();
BlockError(StrBuf.str()); BlockError(StrBuf.str());
// TODO(kschimpf) Remove error recovery once implementation complete. // TODO(kschimpf) Remove error recovery once implementation complete.
if (!VariableDeclarations.empty()) if (!VariableDeclarations->empty())
return VariableDeclarations[0]; return VariableDeclarations->at(0);
report_fatal_error("Unable to continue"); report_fatal_error("Unable to continue");
} }
...@@ -1160,7 +1213,7 @@ public: ...@@ -1160,7 +1213,7 @@ public:
// Returns the value referenced by the given value Index. // Returns the value referenced by the given value Index.
Ice::Operand *getOperand(uint32_t Index) { Ice::Operand *getOperand(uint32_t Index) {
if (Index < CachedNumGlobalValueIDs) { if (Index < CachedNumGlobalValueIDs) {
return Context->getOrCreateGlobalConstantByID(Index); return Context->getGlobalConstantByID(Index);
} }
uint32_t LocalIndex = Index - CachedNumGlobalValueIDs; uint32_t LocalIndex = Index - CachedNumGlobalValueIDs;
if (LocalIndex >= LocalOperands.size()) { if (LocalIndex >= LocalOperands.size()) {
...@@ -2808,41 +2861,15 @@ private: ...@@ -2808,41 +2861,15 @@ private:
// the first call will do the installation. // the first call will do the installation.
void InstallGlobalNamesAndGlobalVarInitializers() { void InstallGlobalNamesAndGlobalVarInitializers() {
if (!GlobalDeclarationNamesAndInitializersInstalled) { if (!GlobalDeclarationNamesAndInitializersInstalled) {
Ice::Translator &Trans = getTranslator(); Context->installGlobalNames();
const Ice::IceString &GlobalPrefix = getFlags().getDefaultGlobalPrefix(); Context->createValueIDs();
if (!GlobalPrefix.empty()) { std::unique_ptr<Ice::VariableDeclarationList> DeclsPtr =
uint32_t NameIndex = 0; Context->getGlobalVariables();
for (Ice::VariableDeclaration *Var : Context->getGlobalVariables()) { const Ice::VariableDeclarationList &Decls = *DeclsPtr;
installDeclarationName(Trans, Var, GlobalPrefix, "global", NameIndex); getTranslator().lowerGlobals(Decls);
}
}
const Ice::IceString &FunctionPrefix =
getFlags().getDefaultFunctionPrefix();
if (!FunctionPrefix.empty()) {
uint32_t NameIndex = 0;
for (Ice::FunctionDeclaration *Func :
Context->getFunctionDeclarationList()) {
installDeclarationName(Trans, Func, FunctionPrefix, "function",
NameIndex);
}
}
getTranslator().lowerGlobals(Context->getGlobalVariables());
GlobalDeclarationNamesAndInitializersInstalled = true; GlobalDeclarationNamesAndInitializersInstalled = true;
} }
} }
void installDeclarationName(Ice::Translator &Trans,
Ice::GlobalDeclaration *Decl,
const Ice::IceString &Prefix, const char *Context,
uint32_t &NameIndex) {
if (!Decl->hasName()) {
Decl->setName(Trans.createUnnamedName(Prefix, NameIndex));
++NameIndex;
} else {
Trans.checkIfUnnamedNameSafe(Decl->getName(), Context, Prefix);
}
}
bool ParseBlock(unsigned BlockID) override; bool ParseBlock(unsigned BlockID) override;
void ExitBlock() override { InstallGlobalNamesAndGlobalVarInitializers(); } void ExitBlock() override { InstallGlobalNamesAndGlobalVarInitializers(); }
......
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