1 // Copyright 2018 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <fstream>
6 #include <iostream>
7
8 #include "src/interpreter/bytecodes.h"
9
10 namespace v8 {
11 namespace internal {
12 namespace interpreter {
13
14 const int kIllegalBytecodeHandler = -1;
15 const int kIllegalBytecodeHandlerEncoding = 255;
16
WriteBytecode(std::ofstream & out,Bytecode bytecode,OperandScale operand_scale,int * count,int offset_table[],int table_index)17 void WriteBytecode(std::ofstream& out, Bytecode bytecode,
18 OperandScale operand_scale, int* count, int offset_table[],
19 int table_index) {
20 DCHECK_NOT_NULL(count);
21 if (Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) {
22 out << " \\\n V(" << Bytecodes::ToString(bytecode, operand_scale, "")
23 << "Handler, interpreter::OperandScale::k" << operand_scale
24 << ", interpreter::Bytecode::k" << Bytecodes::ToString(bytecode) << ")";
25 offset_table[table_index] = *count;
26 (*count)++;
27 } else {
28 offset_table[table_index] = kIllegalBytecodeHandler;
29 }
30 }
31
WriteHeader(const char * header_filename)32 void WriteHeader(const char* header_filename) {
33 std::ofstream out(header_filename);
34
35 out << "// Automatically generated from interpreter/bytecodes.h\n"
36 << "// The following list macro is used to populate the builtins list\n"
37 << "// with the bytecode handlers\n\n"
38 << "#include <stdint.h>\n\n"
39 << "#ifndef V8_BUILTINS_GENERATED_BYTECODES_BUILTINS_LIST\n"
40 << "#define V8_BUILTINS_GENERATED_BYTECODES_BUILTINS_LIST\n\n"
41 << "namespace v8 {\n"
42 << "namespace internal {\n\n"
43 << "#define BUILTIN_LIST_BYTECODE_HANDLERS(V)";
44
45 constexpr int kTableSize =
46 BytecodeOperands::kOperandScaleCount * Bytecodes::kBytecodeCount;
47 int offset_table[kTableSize];
48 int count = 0;
49 int index = 0;
50
51 #define ADD_BYTECODES(Name, ...) \
52 WriteBytecode(out, Bytecode::k##Name, operand_scale, &count, offset_table, \
53 index++);
54 OperandScale operand_scale = OperandScale::kSingle;
55 BYTECODE_LIST(ADD_BYTECODES)
56 int single_count = count;
57 operand_scale = OperandScale::kDouble;
58 BYTECODE_LIST(ADD_BYTECODES)
59 int wide_count = count - single_count;
60 operand_scale = OperandScale::kQuadruple;
61 BYTECODE_LIST(ADD_BYTECODES)
62 #undef ADD_BYTECODES
63 int extra_wide_count = count - wide_count - single_count;
64 CHECK_GT(single_count, wide_count);
65 CHECK_EQ(single_count, Bytecodes::kBytecodeCount);
66 CHECK_EQ(wide_count, extra_wide_count);
67 out << "\n\nconstexpr int kNumberOfBytecodeHandlers = " << single_count
68 << ";\n"
69 << "constexpr int kNumberOfWideBytecodeHandlers = " << wide_count
70 << ";\n\n"
71 << "constexpr uint8_t kIllegalBytecodeHandlerEncoding = "
72 << kIllegalBytecodeHandlerEncoding << ";\n\n"
73 << "// Mapping from Bytecode to a dense form with all the illegal\n"
74 << "// wide Bytecodes removed. Used to index into the builtins table.\n"
75 << "constexpr uint8_t kWideBytecodeToBuiltinsMapping["
76 << "kNumberOfBytecodeHandlers] = { \n";
77
78 for (int i = single_count; i < 2 * single_count; ++i) {
79 int offset = offset_table[i];
80 if (offset == kIllegalBytecodeHandler) {
81 offset = kIllegalBytecodeHandlerEncoding;
82 } else {
83 offset -= single_count;
84 }
85 out << offset << ", ";
86 }
87
88 out << "};\n\n"
89 << "} // namespace internal\n"
90 << "} // namespace v8\n"
91 << "#endif // V8_BUILTINS_GENERATED_BYTECODES_BUILTINS_LIST\n";
92 }
93
94 } // namespace interpreter
95 } // namespace internal
96 } // namespace v8
97
main(int argc,const char * argv[])98 int main(int argc, const char* argv[]) {
99 if (argc != 2) {
100 std::cerr << "Usage: " << argv[0] << " <output filename>\n";
101 std::exit(1);
102 }
103
104 v8::internal::interpreter::WriteHeader(argv[1]);
105
106 return 0;
107 }
108