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
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp
index 46bd261..48f47a9 100644
--- a/src/PNaClTranslator.cpp
+++ b/src/PNaClTranslator.cpp
@@ -163,11 +163,12 @@
NaClBitstreamCursor &Cursor, Ice::ErrorCode &ErrorStatus)
: NaClBitcodeParser(Cursor), Translator(Translator), Header(Header),
ErrorStatus(ErrorStatus), NumErrors(0), NextDefiningFunctionID(0),
+ VariableDeclarations(new Ice::VariableDeclarationList()),
BlockParser(nullptr), StubbedConstCallValue(nullptr) {}
~TopLevelParser() override {}
- Ice::Translator &getTranslator() { return Translator; }
+ Ice::Translator &getTranslator() const { return Translator; }
void setBlockParser(BlockParserBaseClass *NewBlockParser) {
BlockParser = NewBlockParser;
@@ -251,71 +252,27 @@
return reportGetFunctionByIDError(ID);
}
- /// Returns the list of function declarations.
- const FunctionDeclarationListType &getFunctionDeclarationList() const {
- return FunctionDeclarationList;
+ /// Returns the constant associated with the given global value ID.
+ Ice::Constant *getGlobalConstantByID(unsigned ID) {
+ assert(ID < ValueIDConstants.size());
+ return ValueIDConstants[ID];
}
- /// Returns the corresponding constant associated with a global declaration.
- /// (i.e. relocatable).
- Ice::Constant *getOrCreateGlobalConstantByID(unsigned ID) {
- // TODO(kschimpf): Can this be built when creating global initializers?
- Ice::Constant *C;
- if (ID >= ValueIDConstants.size()) {
- C = nullptr;
- unsigned ExpectedSize =
- FunctionDeclarationList.size() + VariableDeclarations.size();
- if (ID >= ExpectedSize)
- ExpectedSize = ID;
- ValueIDConstants.resize(ExpectedSize);
- } else {
- C = ValueIDConstants[ID];
- }
- if (C != nullptr)
- return C;
+ /// Install names for all global values without names. Called after
+ /// the global value symbol table is processed, but before any
+ /// function blocks are processed.
+ void installGlobalNames() {
+ assert(VariableDeclarations);
+ installGlobalVarNames();
+ installFunctionNames();
+ }
- if (isIRGenerationDisabled()) {
- ValueIDConstants[ID] = nullptr;
- return nullptr;
- }
-
- // If reached, no such constant exists, create one.
- // 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;
+ void createValueIDs() {
+ assert(VariableDeclarations);
+ ValueIDConstants.reserve(VariableDeclarations->size() +
+ FunctionDeclarationList.size());
+ createValueIDsForFunctions();
+ createValueIDsForGlobalVars();
}
/// Returns a defined function reference to be used in place of
@@ -328,7 +285,7 @@
for (unsigned i = 0; i < getNumFunctionIDs(); ++i) {
Ice::FunctionDeclaration *Func = getFunctionByID(i);
if (!Func->isProto()) {
- StubbedConstCallValue = getOrCreateGlobalConstantByID(i);
+ StubbedConstCallValue = getGlobalConstantByID(i);
return StubbedConstCallValue;
}
}
@@ -342,27 +299,37 @@
/// Returns the number of global declarations (i.e. IDs) defined in
/// the bitcode file.
unsigned getNumGlobalIDs() const {
- return FunctionDeclarationList.size() + VariableDeclarations.size();
+ if (VariableDeclarations) {
+ return FunctionDeclarationList.size() + VariableDeclarations->size();
+ } else {
+ return ValueIDConstants.size();
+ }
}
/// Creates Count global variable declarations.
void CreateGlobalVariables(size_t Count) {
- assert(VariableDeclarations.empty());
+ assert(VariableDeclarations);
+ assert(VariableDeclarations->empty());
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
/// bitcode file.
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.
Ice::VariableDeclaration *getGlobalVariableByID(unsigned Index) {
- if (Index < VariableDeclarations.size())
- return VariableDeclarations[Index];
+ assert(VariableDeclarations);
+ if (Index < VariableDeclarations->size())
+ return VariableDeclarations->at(Index);
return reportGetGlobalVariableByIDError(Index);
}
@@ -376,9 +343,16 @@
return getGlobalVariableByID(Index - NumFunctionIds);
}
- /// Returns the list of parsed global variable declarations.
- const Ice::VariableDeclarationList &getGlobalVariables() {
- return VariableDeclarations;
+ /// Returns the list of parsed global variable
+ /// declarations. Releases ownership of the current list of global
+ /// 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:
@@ -402,7 +376,7 @@
// actually-defined function.
size_t NextDefiningFunctionID;
// The set of global variables.
- Ice::VariableDeclarationList VariableDeclarations;
+ std::unique_ptr<Ice::VariableDeclarationList> VariableDeclarations;
// Relocatable constants associated with global declarations.
std::vector<Ice::Constant *> ValueIDConstants;
// Error recovery value to use when getFuncSigTypeByID fails.
@@ -432,6 +406,85 @@
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.
void reportBadTypeIDAs(unsigned ID, const ExtendedType *Ty,
ExtendedType::TypeKind WantedType);
@@ -494,11 +547,11 @@
raw_string_ostream StrBuf(Buffer);
StrBuf << "Global index " << Index
<< " not allowed. Out of range. Must be less than "
- << VariableDeclarations.size();
+ << VariableDeclarations->size();
BlockError(StrBuf.str());
// TODO(kschimpf) Remove error recovery once implementation complete.
- if (!VariableDeclarations.empty())
- return VariableDeclarations[0];
+ if (!VariableDeclarations->empty())
+ return VariableDeclarations->at(0);
report_fatal_error("Unable to continue");
}
@@ -1160,7 +1213,7 @@
// Returns the value referenced by the given value Index.
Ice::Operand *getOperand(uint32_t Index) {
if (Index < CachedNumGlobalValueIDs) {
- return Context->getOrCreateGlobalConstantByID(Index);
+ return Context->getGlobalConstantByID(Index);
}
uint32_t LocalIndex = Index - CachedNumGlobalValueIDs;
if (LocalIndex >= LocalOperands.size()) {
@@ -2808,41 +2861,15 @@
// the first call will do the installation.
void InstallGlobalNamesAndGlobalVarInitializers() {
if (!GlobalDeclarationNamesAndInitializersInstalled) {
- Ice::Translator &Trans = getTranslator();
- const Ice::IceString &GlobalPrefix = getFlags().getDefaultGlobalPrefix();
- if (!GlobalPrefix.empty()) {
- uint32_t NameIndex = 0;
- for (Ice::VariableDeclaration *Var : Context->getGlobalVariables()) {
- installDeclarationName(Trans, Var, GlobalPrefix, "global", NameIndex);
- }
- }
- 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());
+ Context->installGlobalNames();
+ Context->createValueIDs();
+ std::unique_ptr<Ice::VariableDeclarationList> DeclsPtr =
+ Context->getGlobalVariables();
+ const Ice::VariableDeclarationList &Decls = *DeclsPtr;
+ getTranslator().lowerGlobals(Decls);
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;
void ExitBlock() override { InstallGlobalNamesAndGlobalVarInitializers(); }