Chromium Code Reviews| Index: src/PNaClTranslator.cpp |
| diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp |
| index 023a433119266995c2ba026c305db89d07112148..328fdeffad864b9db3802280173dc04496c8b2bc 100644 |
| --- a/src/PNaClTranslator.cpp |
| +++ b/src/PNaClTranslator.cpp |
| @@ -27,6 +27,7 @@ |
| #pragma clang diagnostic push |
| #pragma clang diagnostic ignored "-Wunused-parameter" |
| +#include "llvm/ADT/Hashing.h" |
| #include "llvm/ADT/SmallString.h" |
| #include "llvm/Bitcode/NaCl/NaClBitcodeDecoders.h" |
| #include "llvm/Bitcode/NaCl/NaClBitcodeDefs.h" |
| @@ -36,8 +37,19 @@ |
| #include "llvm/Support/Format.h" |
| #include "llvm/Support/MemoryBuffer.h" |
| #include "llvm/Support/raw_ostream.h" |
| +#include <unordered_set> |
| #pragma clang diagnostic pop |
| +// Define a hash function for SmallString's, so that it can be used in hash |
| +// tables. |
| +namespace std { |
| +template <unsigned InternalLen> struct hash<llvm::SmallString<InternalLen>> { |
| + size_t operator()(const llvm::SmallString<InternalLen> &Key) const { |
| + return llvm::hash_combine_range(Key.begin(), Key.end()); |
| + } |
| +}; |
| +} // end of namespace std. |
|
Jim Stichnoth
2015/09/16 19:54:37
no period, for consistency
Karl
2015/09/16 20:51:43
Done.
|
| + |
| namespace { |
| using namespace llvm; |
| @@ -1160,23 +1172,60 @@ public: |
| protected: |
| using StringType = SmallString<128>; |
| + // Returns the name to identify the kind of symbol table this is |
| + // in error messages. |
| + virtual const char *getTableKind() const = 0; |
| + |
| // Associates Name with the value defined by the given Index. |
| virtual void setValueName(NaClBcIndexSize_t Index, StringType &Name) = 0; |
| // Associates Name with the value defined by the given Index; |
| virtual void setBbName(NaClBcIndexSize_t Index, StringType &Name) = 0; |
| + // Reports that the assignment of Name to the value associated with |
| + // index is not possible, for the given Context. |
| + void reportUnableToAssign(const char *Context, NaClBcIndexSize_t Index, |
| + StringType &Name); |
| + |
| private: |
| + using NamesSetType = std::unordered_set<StringType>; |
| + NamesSetType ValueNames; |
| + NamesSetType BlockNames; |
| + |
| void ProcessRecord() override; |
| - void convertToString(StringType &ConvertedName) { |
| + // Extracts out ConvertedName. Returns true if unique wrt to Names. |
| + bool convertToString(NamesSetType &Names, StringType &ConvertedName) { |
| const NaClBitcodeRecord::RecordVector &Values = Record.GetValues(); |
| for (size_t i = 1, e = Values.size(); i != e; ++i) { |
| ConvertedName += static_cast<char>(Values[i]); |
| } |
| + auto Pair = Names.insert(ConvertedName); |
| + return Pair.second; |
| } |
| + |
| + void ReportDuplicateName(const char *NameCat, StringType &Name); |
| }; |
| +void ValuesymtabParser::reportUnableToAssign(const char *Context, |
| + NaClBcIndexSize_t Index, |
| + StringType &Name) { |
| + std::string Buffer; |
| + raw_string_ostream StrBuf(Buffer); |
| + StrBuf << getTableKind() << " " << getBlockName() << ": " << Context |
| + << " name '" << Name << "' can't be associated with index " << Index; |
| + Error(StrBuf.str()); |
| +} |
| + |
| +void ValuesymtabParser::ReportDuplicateName(const char *NameCat, |
| + StringType &Name) { |
| + std::string Buffer; |
| + raw_string_ostream StrBuf(Buffer); |
| + StrBuf << getTableKind() << " " << getBlockName() << " defines duplicate " |
| + << NameCat << " name: '" << Name << "'"; |
| + Error(StrBuf.str()); |
| +} |
| + |
| void ValuesymtabParser::ProcessRecord() { |
| const NaClBitcodeRecord::RecordVector &Values = Record.GetValues(); |
| StringType ConvertedName; |
| @@ -1185,16 +1234,20 @@ void ValuesymtabParser::ProcessRecord() { |
| // VST_ENTRY: [ValueId, namechar x N] |
| if (!isValidRecordSizeAtLeast(2, "value entry")) |
| return; |
| - convertToString(ConvertedName); |
| - setValueName(Values[0], ConvertedName); |
| + if (convertToString(ValueNames, ConvertedName)) |
| + setValueName(Values[0], ConvertedName); |
| + else |
| + ReportDuplicateName("value", ConvertedName); |
| return; |
| } |
| case naclbitc::VST_CODE_BBENTRY: { |
| // VST_BBENTRY: [BbId, namechar x N] |
| if (!isValidRecordSizeAtLeast(2, "basic block entry")) |
| return; |
| - convertToString(ConvertedName); |
| - setBbName(Values[0], ConvertedName); |
| + if (convertToString(BlockNames, ConvertedName)) |
| + setBbName(Values[0], ConvertedName); |
| + else |
| + ReportDuplicateName("block", ConvertedName); |
| return; |
| } |
| default: |
| @@ -2884,19 +2937,10 @@ private: |
| return reinterpret_cast<FunctionParser *>(GetEnclosingParser()); |
| } |
| - void setValueName(NaClBcIndexSize_t Index, StringType &Name) override; |
| - void setBbName(NaClBcIndexSize_t Index, StringType &Name) override; |
| + const char *getTableKind() const final { return "Function"; } |
| - // Reports that the assignment of Name to the value associated with |
| - // index is not possible, for the given Context. |
| - void reportUnableToAssign(const char *Context, NaClBcIndexSize_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 setValueName(NaClBcIndexSize_t Index, StringType &Name) final; |
| + void setBbName(NaClBcIndexSize_t Index, StringType &Name) final; |
| }; |
| void FunctionValuesymtabParser::setValueName(NaClBcIndexSize_t Index, |
| @@ -2904,7 +2948,7 @@ void FunctionValuesymtabParser::setValueName(NaClBcIndexSize_t Index, |
| // Note: We check when Index is too small, so that we can error recover |
| // (FP->getOperand will create fatal error). |
| if (Index < getFunctionParser()->getNumGlobalIDs()) { |
| - reportUnableToAssign("instruction", Index, Name); |
| + reportUnableToAssign("Global value", Index, Name); |
| return; |
| } |
| if (isIRGenerationDisabled()) |
| @@ -2916,7 +2960,7 @@ void FunctionValuesymtabParser::setValueName(NaClBcIndexSize_t Index, |
| V->setName(getFunctionParser()->getFunc(), Nm); |
| } |
| } else { |
| - reportUnableToAssign("variable", Index, Name); |
| + reportUnableToAssign("Local value", Index, Name); |
| } |
| } |
| @@ -2927,7 +2971,7 @@ void FunctionValuesymtabParser::setBbName(NaClBcIndexSize_t Index, |
| if (isIRGenerationDisabled()) |
| return; |
| if (Index >= getFunctionParser()->getFunc()->getNumNodes()) { |
| - reportUnableToAssign("block", Index, Name); |
| + reportUnableToAssign("Basic block", Index, Name); |
| return; |
| } |
| std::string Nm(Name.data(), Name.size()); |
| @@ -3010,8 +3054,9 @@ public: |
| private: |
| Ice::TimerMarker Timer; |
| - void setValueName(NaClBcIndexSize_t Index, StringType &Name) override; |
| - void setBbName(NaClBcIndexSize_t Index, StringType &Name) override; |
| + const char *getTableKind() const final { return "Module"; } |
| + void setValueName(NaClBcIndexSize_t Index, StringType &Name) final; |
| + void setBbName(NaClBcIndexSize_t Index, StringType &Name) final; |
| }; |
| void ModuleValuesymtabParser::setValueName(NaClBcIndexSize_t Index, |
| @@ -3022,11 +3067,7 @@ void ModuleValuesymtabParser::setValueName(NaClBcIndexSize_t Index, |
| void ModuleValuesymtabParser::setBbName(NaClBcIndexSize_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()); |
| + reportUnableToAssign("Basic block", Index, Name); |
| } |
| bool ModuleParser::ParseBlock(unsigned BlockID) { |