[XLA:Tool] Make Hlo parser report the location of the already defined instrucion/computation.

PiperOrigin-RevId: 185213461
This commit is contained in:
A. Unique TensorFlower 2018-02-09 16:57:14 -08:00 committed by TensorFlower Gardener
parent 7a5d775685
commit 816f59e6ab
2 changed files with 58 additions and 19 deletions

View File

@ -220,10 +220,13 @@ class HloParser {
bool AddComputation(const string& name, HloComputation* computation,
LocTy name_loc);
// The map from the instruction name to the instruction. This does not own the
// instructions.
std::unordered_map<string, HloInstruction*> instruction_pool_;
std::unordered_map<string, HloComputation*> computation_pool_;
// The map from the instruction/computation name to the
// instruction/computation itself and it's location. This does not own the
// pointers.
std::unordered_map<string, std::pair<HloInstruction*, LocTy>>
instruction_pool_;
std::unordered_map<string, std::pair<HloComputation*, LocTy>>
computation_pool_;
HloLexer lexer_;
std::unique_ptr<HloModule> module_;
@ -340,15 +343,16 @@ bool HloParser::ParseComputation(HloComputation** entry_computation) {
return false;
}
HloInstruction* root =
tensorflow::gtl::FindPtrOrNull(instruction_pool_, root_name);
std::pair<HloInstruction*, LocTy>* root_node =
tensorflow::gtl::FindOrNull(instruction_pool_, root_name);
// This means some instruction was marked as ROOT but we didn't find it in the
// pool, which should not happen.
if (!root_name.empty() && root == nullptr) {
if (!root_name.empty() && root_node == nullptr) {
LOG(FATAL) << "instruction " << root_name
<< " was marked as ROOT but the parser has not seen it before";
}
HloInstruction* root = root_node == nullptr ? nullptr : root_node->first;
// Now root can be either an existing instruction or a nullptr. If it's a
// nullptr, the implementation of Builder will set the last instruction as
// root instruction.
@ -1229,13 +1233,13 @@ bool HloParser::ParseInstructionNames(
if (!ParseName(&name)) {
return Error(loc, "expects a instruction name");
}
HloInstruction* instr =
tensorflow::gtl::FindPtrOrNull(instruction_pool_, name);
std::pair<HloInstruction*, LocTy>* instr =
tensorflow::gtl::FindOrNull(instruction_pool_, name);
if (!instr) {
return TokenError(
Printf("instruction '%s' is not defined", name.c_str()));
}
instructions->push_back(instr);
instructions->push_back(instr->first);
} while (EatIfPresent(TokKind::kComma));
return ParseToken(TokKind::kRbrace,
@ -1705,12 +1709,12 @@ bool HloParser::ParseOperands(std::vector<HloInstruction*>* operands) {
if (!ParseName(&name)) {
return false;
}
HloInstruction* instruction =
tensorflow::gtl::FindPtrOrNull(instruction_pool_, name);
std::pair<HloInstruction*, LocTy>* instruction =
tensorflow::gtl::FindOrNull(instruction_pool_, name);
if (!instruction) {
return Error(loc, StrCat("instruction does not exist: ", name));
}
operands->push_back(instruction);
operands->push_back(instruction->first);
} while (EatIfPresent(TokKind::kComma));
}
return ParseToken(TokKind::kRparen, "expects ')' at the end of operands");
@ -1957,10 +1961,12 @@ bool HloParser::ParseComputationName(HloComputation** value) {
if (!ParseName(&name)) {
return Error(loc, "expects computation name");
}
*value = tensorflow::gtl::FindPtrOrNull(computation_pool_, name);
if (*value == nullptr) {
std::pair<HloComputation*, LocTy>* computation =
tensorflow::gtl::FindOrNull(computation_pool_, name);
if (computation == nullptr) {
return Error(loc, StrCat("computation does not exist: ", name));
}
*value = computation->first;
return true;
}
@ -2576,18 +2582,22 @@ bool HloParser::EatIfPresent(TokKind kind) {
bool HloParser::AddInstruction(const string& name, HloInstruction* instruction,
LocTy name_loc) {
auto result = instruction_pool_.insert({name, instruction});
auto result = instruction_pool_.insert({name, {instruction, name_loc}});
if (!result.second) {
return Error(name_loc, StrCat("instruction already exists: ", name));
Error(name_loc, StrCat("instruction already exists: ", name));
return Error(/*loc=*/result.first->second.second,
"instruction previously defined here");
}
return true;
}
bool HloParser::AddComputation(const string& name, HloComputation* computation,
LocTy name_loc) {
auto result = computation_pool_.insert({name, computation});
auto result = computation_pool_.insert({name, {computation, name_loc}});
if (!result.second) {
return Error(name_loc, StrCat("computation already exists: ", name));
Error(name_loc, StrCat("computation already exists: ", name));
return Error(/*loc=*/result.first->second.second,
"computation previously defined here");
}
return true;
}

View File

@ -1275,6 +1275,35 @@ ENTRY consts {
"one computation should have only one ROOT");
}
TEST_F(HloParserTest, InstructionExists) {
const string original = R"(HloModule comp_exists
c1 {
instr = f32[1]{0} constant({12345})
}
c2 {
instr = f32[1]{0} constant({67890})
})";
ExpectHasSubstr(Parse(original).status().error_message(),
R"(was parsing 3:3: error: instruction previously defined here
instr = f32[1]{0} constant({12345})
^)");
}
TEST_F(HloParserTest, ComputationExists) {
const string original = R"(HloModule comp_exists
comp {
const1 = f32[1]{0} constant({12345})
}
comp {
const2 = f32[1]{0} constant({67890})
})";
ExpectHasSubstr(Parse(original).status().error_message(),
R"(was parsing 2:1: error: computation previously defined here
comp {
^)");
}
} // namespace
} // namespace tools
} // namespace xla