Fix symbol table handling in functions.
Also fixes minor issues with branches in instructions (i.e. defining
entry node and computing predecessors).
BUG= https://code.google.com/p/nativeclient/issues/detail?id=3892
R=stichnot@chromium.org
Review URL: https://codereview.chromium.org/561823002
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp
index b05b6be..5d889ff 100644
--- a/src/PNaClTranslator.cpp
+++ b/src/PNaClTranslator.cpp
@@ -739,21 +739,27 @@
installGlobalVar();
}
-// Parses a valuesymtab block in the bitcode file.
+/// Base class for parsing a valuesymtab block in the bitcode file.
class ValuesymtabParser : public BlockParserBaseClass {
- typedef SmallString<128> StringType;
+ ValuesymtabParser(const ValuesymtabParser &) LLVM_DELETED_FUNCTION;
+ void operator=(const ValuesymtabParser &) LLVM_DELETED_FUNCTION;
public:
- ValuesymtabParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser,
- bool AllowBbEntries)
- : BlockParserBaseClass(BlockID, EnclosingParser),
- AllowBbEntries(AllowBbEntries) {}
+ ValuesymtabParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
+ : BlockParserBaseClass(BlockID, EnclosingParser) {}
virtual ~ValuesymtabParser() LLVM_OVERRIDE {}
+protected:
+ typedef SmallString<128> StringType;
+
+ // Associates Name with the value defined by the given Index.
+ virtual void setValueName(uint64_t Index, StringType &Name) = 0;
+
+ // Associates Name with the value defined by the given Index;
+ virtual void setBbName(uint64_t Index, StringType &Name) = 0;
+
private:
- // True if entries to name basic blocks allowed.
- bool AllowBbEntries;
virtual void ProcessRecord() LLVM_OVERRIDE;
@@ -774,25 +780,16 @@
if (!isValidRecordSizeAtLeast(2, "Valuesymtab value entry"))
return;
ConvertToString(ConvertedName);
- Value *V = Context->getGlobalValueByID(Values[0]);
- if (V == NULL) {
- std::string Buffer;
- raw_string_ostream StrBuf(Buffer);
- StrBuf << "Invalid global address ID in valuesymtab: " << Values[0];
- Error(StrBuf.str());
- return;
- }
- V->setName(StringRef(ConvertedName.data(), ConvertedName.size()));
+ setValueName(Values[0], ConvertedName);
return;
}
case naclbitc::VST_CODE_BBENTRY: {
// VST_BBENTRY: [BbId, namechar x N]
- // For now, since we aren't processing function blocks, don't handle.
- if (AllowBbEntries) {
- Error("Valuesymtab bb entry not implemented");
+ if (!isValidRecordSizeAtLeast(2, "Valuesymtab basic block entry"))
return;
- }
- break;
+ ConvertToString(ConvertedName);
+ setBbName(Values[0], ConvertedName);
+ return;
}
default:
break;
@@ -802,10 +799,13 @@
return;
}
+class FunctionValuesymtabParser;
+
/// Parses function blocks in the bitcode file.
class FunctionParser : public BlockParserBaseClass {
FunctionParser(const FunctionParser &) LLVM_DELETED_FUNCTION;
FunctionParser &operator=(const FunctionParser &) LLVM_DELETED_FUNCTION;
+ friend class FunctionValuesymtabParser;
public:
FunctionParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
@@ -819,6 +819,7 @@
Func->setReturnType(Context->convertToIceType(LLVMFunc->getReturnType()));
Func->setInternal(LLVMFunc->hasInternalLinkage());
CurrentNode = InstallNextBasicBlock();
+ Func->setEntryNode(CurrentNode);
for (Function::const_arg_iterator ArgI = LLVMFunc->arg_begin(),
ArgE = LLVMFunc->arg_end();
ArgI != ArgE; ++ArgI) {
@@ -1293,6 +1294,7 @@
Node->appendInst(Ice::InstUnreachable::create(Func));
}
}
+ Func->computePredecessors();
// Note: Once any errors have been found, we turn off all
// translation of all remaining functions. This allows use to see
// multiple errors, without adding extra checks to the translator
@@ -1759,15 +1761,80 @@
}
}
+// Parses valuesymtab blocks appearing in a function block.
+class FunctionValuesymtabParser : public ValuesymtabParser {
+ FunctionValuesymtabParser(const FunctionValuesymtabParser &)
+ LLVM_DELETED_FUNCTION;
+ void operator=(const FunctionValuesymtabParser &) LLVM_DELETED_FUNCTION;
+
+public:
+ FunctionValuesymtabParser(unsigned BlockID, FunctionParser *EnclosingParser)
+ : ValuesymtabParser(BlockID, EnclosingParser) {}
+
+private:
+ // Returns the enclosing function parser.
+ FunctionParser *getFunctionParser() const {
+ return reinterpret_cast<FunctionParser *>(GetEnclosingParser());
+ }
+
+ virtual void setValueName(uint64_t Index, StringType &Name) LLVM_OVERRIDE;
+ virtual void setBbName(uint64_t Index, StringType &Name) LLVM_OVERRIDE;
+
+ // Reports that the assignment of Name to the value associated with
+ // index is not possible, for the given Context.
+ void reportUnableToAssign(const char *Context, uint64_t Index,
+ StringType &Name) {
+ std::string Buffer;
+ raw_string_ostream StrBuf(Buffer);
+ StrBuf << "Function-local " << Context << " name '" << Name
+ << "' can't be associated with index " << Index;
+ Error(StrBuf.str());
+ }
+};
+
+void FunctionValuesymtabParser::setValueName(uint64_t Index, StringType &Name) {
+ // Note: We check when Index is too small, so that we can error recover
+ // (FP->getOperand will create fatal error).
+ if (Index < getFunctionParser()->CachedNumGlobalValueIDs) {
+ reportUnableToAssign("instruction", Index, Name);
+ // TODO(kschimpf) Remove error recovery once implementation complete.
+ return;
+ }
+ Ice::Operand *Op = getFunctionParser()->getOperand(Index);
+ if (Ice::Variable *V = dyn_cast<Ice::Variable>(Op)) {
+ std::string Nm(Name.data(), Name.size());
+ V->setName(Nm);
+ } else {
+ reportUnableToAssign("variable", Index, Name);
+ }
+}
+
+void FunctionValuesymtabParser::setBbName(uint64_t Index, StringType &Name) {
+ if (Index >= getFunctionParser()->Func->getNumNodes()) {
+ reportUnableToAssign("block", Index, Name);
+ return;
+ }
+ std::string Nm(Name.data(), Name.size());
+ getFunctionParser()->Func->getNodes()[Index]->setName(Nm);
+}
+
bool FunctionParser::ParseBlock(unsigned BlockID) {
switch (BlockID) {
case naclbitc::CONSTANTS_BLOCK_ID: {
ConstantsParser Parser(BlockID, this);
return Parser.ParseThisBlock();
}
- default:
- return BlockParserBaseClass::ParseBlock(BlockID);
+ case naclbitc::VALUE_SYMTAB_BLOCK_ID: {
+ if (PNaClAllowLocalSymbolTables) {
+ FunctionValuesymtabParser Parser(BlockID, this);
+ return Parser.ParseThisBlock();
+ }
+ break;
}
+ default:
+ break;
+ }
+ return BlockParserBaseClass::ParseBlock(BlockID);
}
/// Parses the module block in the bitcode file.
@@ -1784,6 +1851,42 @@
virtual void ProcessRecord() LLVM_OVERRIDE;
};
+class ModuleValuesymtabParser : public ValuesymtabParser {
+ ModuleValuesymtabParser(const ModuleValuesymtabParser &)
+ LLVM_DELETED_FUNCTION;
+ void operator=(const ModuleValuesymtabParser &) LLVM_DELETED_FUNCTION;
+
+public:
+ ModuleValuesymtabParser(unsigned BlockID, ModuleParser *MP)
+ : ValuesymtabParser(BlockID, MP) {}
+
+ virtual ~ModuleValuesymtabParser() LLVM_OVERRIDE {}
+
+private:
+ virtual void setValueName(uint64_t Index, StringType &Name) LLVM_OVERRIDE;
+ virtual void setBbName(uint64_t Index, StringType &Name) LLVM_OVERRIDE;
+};
+
+void ModuleValuesymtabParser::setValueName(uint64_t Index, StringType &Name) {
+ Value *V = Context->getGlobalValueByID(Index);
+ if (V == NULL) {
+ std::string Buffer;
+ raw_string_ostream StrBuf(Buffer);
+ StrBuf << "Invalid global address ID in valuesymtab: " << Index;
+ Error(StrBuf.str());
+ return;
+ }
+ V->setName(StringRef(Name.data(), Name.size()));
+}
+
+void ModuleValuesymtabParser::setBbName(uint64_t Index, StringType &Name) {
+ std::string Buffer;
+ raw_string_ostream StrBuf(Buffer);
+ StrBuf << "Can't define basic block name at global level: '" << Name
+ << "' -> " << Index;
+ Error(StrBuf.str());
+}
+
bool ModuleParser::ParseBlock(unsigned BlockID) LLVM_OVERRIDE {
switch (BlockID) {
case naclbitc::BLOCKINFO_BLOCK_ID:
@@ -1797,7 +1900,7 @@
return Parser.ParseThisBlock();
}
case naclbitc::VALUE_SYMTAB_BLOCK_ID: {
- ValuesymtabParser Parser(BlockID, this, false);
+ ModuleValuesymtabParser Parser(BlockID, this);
return Parser.ParseThisBlock();
}
case naclbitc::FUNCTION_BLOCK_ID: {