diff options
Diffstat (limited to 'deps/v8/test/cctest/disasm-regex-helper.cc')
-rw-r--r-- | deps/v8/test/cctest/disasm-regex-helper.cc | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/deps/v8/test/cctest/disasm-regex-helper.cc b/deps/v8/test/cctest/disasm-regex-helper.cc new file mode 100644 index 0000000000..2b3b4f97a5 --- /dev/null +++ b/deps/v8/test/cctest/disasm-regex-helper.cc @@ -0,0 +1,291 @@ +// Copyright 2019 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "test/cctest/disasm-regex-helper.h" + +#include "src/api/api-inl.h" +#include "src/diagnostics/disassembler.h" +#include "src/objects/objects-inl.h" +#include "test/cctest/cctest.h" + +namespace v8 { +namespace internal { + +namespace { +std::string DisassembleFunction(const char* function) { + v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext(); + Handle<JSFunction> f = Handle<JSFunction>::cast( + v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( + CcTest::global()->Get(context, v8_str(function)).ToLocalChecked()))); + + Address begin = f->code().raw_instruction_start(); + Address end = f->code().raw_instruction_end(); + Isolate* isolate = CcTest::i_isolate(); + std::ostringstream os; + Disassembler::Decode(isolate, &os, reinterpret_cast<byte*>(begin), + reinterpret_cast<byte*>(end), + CodeReference(handle(f->code(), isolate))); + return os.str(); +} + +} // namespace + +bool CheckDisassemblyRegexPatterns( + const char* function_name, const std::vector<std::string>& patterns_array) { + std::istringstream reader(DisassembleFunction(function_name)); + size_t size = patterns_array.size(); + DCHECK_GT(size, 0); + + std::smatch match; + std::string line; + RegexParser parser; + const std::string& first_pattern = patterns_array[0]; + while (std::getline(reader, line)) { + RegexParser::Status status = parser.ProcessPattern(line, first_pattern); + if (status == RegexParser::Status::kSuccess) { + CHECK(std::getline(reader, line)); + for (size_t i = 1; i < size; i++) { + const std::string& pattern = patterns_array[i]; + status = parser.ProcessPattern(line, pattern); + if (status != RegexParser::Status::kSuccess) { + std::cout << "Pattern \"" << pattern << "\" not found" << std::endl; + std::cout << "Line: \"" << line << "\":" << std::endl; + parser.PrintSymbols(std::cout); + return false; + } + CHECK(std::getline(reader, line)); + } + + return true; + } + } + return false; +} + +namespace { +void RegexCheck( + const std::vector<std::string>& inputs, + const std::vector<std::string>& patterns, + RegexParser::Status expected_status, + std::function<void(const RegexParser&)> func = [](const RegexParser&) {}) { + size_t size = patterns.size(); + CHECK_EQ(size, inputs.size()); + RegexParser parser; + RegexParser::Status status; + size_t i = 0; + for (; i < size - 1; i++) { + const std::string& line = inputs[i]; + const std::string& pattern = patterns[i]; + status = parser.ProcessPattern(line, pattern); + CHECK_EQ(status, RegexParser::Status::kSuccess); + } + const std::string& line = inputs[i]; + const std::string& pattern = patterns[i]; + status = parser.ProcessPattern(line, pattern); + + if (status != expected_status) { + parser.PrintSymbols(std::cout); + } + CHECK_EQ(status, expected_status); + func(parser); +} + +// Check a line against a pattern. +void RegexCheckOne( + const std::string& line, const std::string& pattern, + RegexParser::Status expected_status, + std::function<void(const RegexParser&)> func = [](const RegexParser&) {}) { + RegexParser parser; + RegexParser::Status status = parser.ProcessPattern(line, pattern); + CHECK_EQ(status, expected_status); + func(parser); +} + +void TestSymbolValue(const std::string& sym_name, const std::string& value, + const RegexParser& p) { + CHECK(p.IsSymbolDefined(sym_name)); + CHECK_EQ(p.GetSymbolMatchedValue(sym_name).compare(value), 0); +} + +} // namespace + +// clang-format off +TEST(RegexParserSingleLines) { + // + // Simple one-liners for found/not found. + // + RegexCheckOne(" a b a b c a", + "a b c", + RegexParser::Status::kSuccess); + + RegexCheckOne(" a b a bc a", + "a b c", + RegexParser::Status::kNotMatched); + + RegexCheckOne("aaabbaaa", + "ab.*?a", + RegexParser::Status::kSuccess); + + RegexCheckOne("aaabbaa", + "^(?:aa+|b)+$", + RegexParser::Status::kSuccess); + + RegexCheckOne("aaabba", + "^(?:aa+|b)+$", + RegexParser::Status::kNotMatched); + + RegexCheckOne("(aaa)", + "\\(a+\\)", + RegexParser::Status::kSuccess); + + RegexCheckOne("r19 qwerty", + "r<<Def:[0-9]+>>", + RegexParser::Status::kSuccess, + [] (const RegexParser& p) { + TestSymbolValue("Def", "19", p); + }); + + RegexCheckOne("r19 qwerty", + "r<<Def:[a-z]+>>", + RegexParser::Status::kSuccess, + [] (const RegexParser& p) { + TestSymbolValue("Def", "ty", p); + }); + + // Backreference/submatch groups are forbidden. + RegexCheckOne("aaabba", + "((aa+)|b)+?", + RegexParser::Status::kWrongPattern); + + // Using passive groups. + RegexCheckOne("aaabba", + "(?:(?:aa+)|b)+?", + RegexParser::Status::kSuccess); + + // + // Symbol definitions. + // + RegexCheckOne("r19 r20", + "r<<Def:19>>", + RegexParser::Status::kSuccess, + [] (const RegexParser& p) { + TestSymbolValue("Def", "19", p); + }); + + RegexCheckOne("r19 r20", + "r<<Def:[0-9]+>>", + RegexParser::Status::kSuccess, + [] (const RegexParser& p) { + TestSymbolValue("Def", "19", p); + }); + + RegexCheckOne("r19 r20", + "r<<Def0:[0-9]+>>.*?r<<Def1:[0-9]+>>", + RegexParser::Status::kSuccess, + [] (const RegexParser& p) { + TestSymbolValue("Def0", "19", p); + TestSymbolValue("Def1", "20", p); + }); + + RegexCheckOne("r19 r20", + "r<<Def0:[0-9]+>>.*?r[0-9]", + RegexParser::Status::kSuccess, + [] (const RegexParser& p) { + TestSymbolValue("Def0", "19", p); + }); + + // Checks that definitions are not committed unless the pattern is matched. + RegexCheckOne("r19", + "r<<Def0:[0-9]+>>.*?r<<Def1:[0-9]+>>", + RegexParser::Status::kNotMatched, + [] (const RegexParser& p) { + CHECK(!p.IsSymbolDefined("Def0")); + CHECK(!p.IsSymbolDefined("Def1")); + }); + + RegexCheckOne("r19 r19 r1", + "r<<Def0:[0-9]+>>.*?r<<Def0:[0-9]+>> r<<Def1:[0-9]+>>", + RegexParser::Status::kRedefinition, + [] (const RegexParser& p) { + CHECK(!p.IsSymbolDefined("Def0")); + CHECK(!p.IsSymbolDefined("Def1")); + }); + + RegexCheckOne("r19 r1", + "r<<Def0:[0-9]+>> (r1)", + RegexParser::Status::kWrongPattern, + [] (const RegexParser& p) { + CHECK(!p.IsSymbolDefined("Def0")); + }); + + // + // Undefined symbol references. + // + RegexCheckOne("r19 r1", + "r[0-9].*?r<<Undef>>", + RegexParser::Status::kDefNotFound, + [] (const RegexParser& p) { + CHECK(!p.IsSymbolDefined("Undef")); + }); + + RegexCheckOne("r19 r1", + "r<<Def0:[0-9]+>>.*?<<Undef>>", + RegexParser::Status::kDefNotFound, + [] (const RegexParser& p) { + CHECK(!p.IsSymbolDefined("Undef")); + CHECK(!p.IsSymbolDefined("Def0")); + }); + + RegexCheckOne("r19 r19", + "r<<Def0:[0-9]+>>.*?<<Def0>>", + RegexParser::Status::kDefNotFound, + [] (const RegexParser& p) { + CHECK(!p.IsSymbolDefined("Def0")); + }); +} + +TEST(RegexParserMultiLines) { + RegexCheck({ " a b a b c a", + " a b a b c a" }, + { "a b c", + "a b c" }, + RegexParser::Status::kSuccess); + + RegexCheck({ "r16 = r15", + "r17 = r16" }, + { "<<Def:r[0-9]+>> = r[0-9]+", + "[0-9]+ = <<Def>>" }, + RegexParser::Status::kSuccess, + [] (const RegexParser& p) { + TestSymbolValue("Def", "r16", p); + }); + + RegexCheck({ "r16 = r15 + r13", + "r17 = r16 + r14", + "r19 = r14" }, + { "<<Def0:r[0-9]+>> = r[0-9]+", + "<<Def1:r[0-9]+>> = <<Def0>> \\+ <<Def2:r[0-9]+>>", + "<<Def3:r[0-9]+>> = <<Def2>>" }, + RegexParser::Status::kSuccess, + [] (const RegexParser& p) { + TestSymbolValue("Def0", "r16", p); + TestSymbolValue("Def1", "r17", p); + TestSymbolValue("Def2", "r14", p); + TestSymbolValue("Def3", "r19", p); + }); + + // Constraint is not met for Def (r19 != r16). + RegexCheck({ "r16 = r15", + "r17 = r19" }, + { "<<Def:r[0-9]+>> = r[0-9]+", + "[0-9]+ = <<Def>>" }, + RegexParser::Status::kNotMatched, + [] (const RegexParser& p) { + TestSymbolValue("Def", "r16", p); + }); +} +// clang-format on + +} // namespace internal +} // namespace v8 |