blob: 7317402fd5ec065e3eac540f805907aa2fbabfe3 [file] [log] [blame]
// Copyright 2018 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 <fstream>
#include <iostream>
#include "src/interpreter/bytecodes.h"
namespace v8 {
namespace internal {
namespace interpreter {
const int kIllegalBytecodeHandler = -1;
const int kIllegalBytecodeHandlerEncoding = 255;
void WriteBytecode(std::ofstream& out, Bytecode bytecode,
OperandScale operand_scale, int* count, int offset_table[],
int table_index) {
DCHECK_NOT_NULL(count);
if (Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) {
out << " \\\n V(" << Bytecodes::ToString(bytecode, operand_scale, "")
<< "Handler, interpreter::OperandScale::k" << operand_scale
<< ", interpreter::Bytecode::k" << Bytecodes::ToString(bytecode) << ")";
offset_table[table_index] = *count;
(*count)++;
} else {
offset_table[table_index] = kIllegalBytecodeHandler;
}
}
void WriteHeader(const char* header_filename) {
std::ofstream out(header_filename);
out << "// Automatically generated from interpreter/bytecodes.h\n"
<< "// The following list macro is used to populate the builtins list\n"
<< "// with the bytecode handlers\n\n"
<< "#include <stdint.h>\n\n"
<< "#ifndef V8_BUILTINS_GENERATED_BYTECODES_BUILTINS_LIST\n"
<< "#define V8_BUILTINS_GENERATED_BYTECODES_BUILTINS_LIST\n\n"
<< "namespace v8 {\n"
<< "namespace internal {\n\n"
<< "#define BUILTIN_LIST_BYTECODE_HANDLERS(V)";
constexpr int kTableSize =
BytecodeOperands::kOperandScaleCount * Bytecodes::kBytecodeCount;
int offset_table[kTableSize];
int count = 0;
int index = 0;
#define ADD_BYTECODES(Name, ...) \
WriteBytecode(out, Bytecode::k##Name, operand_scale, &count, offset_table, \
index++);
OperandScale operand_scale = OperandScale::kSingle;
BYTECODE_LIST(ADD_BYTECODES)
int single_count = count;
operand_scale = OperandScale::kDouble;
BYTECODE_LIST(ADD_BYTECODES)
int wide_count = count - single_count;
operand_scale = OperandScale::kQuadruple;
BYTECODE_LIST(ADD_BYTECODES)
#undef ADD_BYTECODES
int extra_wide_count = count - wide_count - single_count;
CHECK_GT(single_count, wide_count);
CHECK_EQ(single_count, Bytecodes::kBytecodeCount);
CHECK_EQ(wide_count, extra_wide_count);
out << "\n\nconstexpr int kNumberOfBytecodeHandlers = " << single_count
<< ";\n"
<< "constexpr int kNumberOfWideBytecodeHandlers = " << wide_count
<< ";\n\n"
<< "constexpr uint8_t kIllegalBytecodeHandlerEncoding = "
<< kIllegalBytecodeHandlerEncoding << ";\n\n"
<< "// Mapping from Bytecode to a dense form with all the illegal\n"
<< "// wide Bytecodes removed. Used to index into the builtins table.\n"
<< "constexpr uint8_t kWideBytecodeToBuiltinsMapping["
<< "kNumberOfBytecodeHandlers] = { \n";
for (int i = single_count; i < 2 * single_count; ++i) {
int offset = offset_table[i];
if (offset == kIllegalBytecodeHandler) {
offset = kIllegalBytecodeHandlerEncoding;
} else {
offset -= single_count;
}
out << offset << ", ";
}
out << "};\n\n"
<< "} // namespace internal\n"
<< "} // namespace v8\n"
<< "#endif // V8_BUILTINS_GENERATED_BYTECODES_BUILTINS_LIST\n";
}
} // namespace interpreter
} // namespace internal
} // namespace v8
int main(int argc, const char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " <output filename>\n";
std::exit(1);
}
v8::internal::interpreter::WriteHeader(argv[1]);
return 0;
}