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