Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / js / src / jit / GenerateLIRFiles.py
blob6fe2e8ae8d84f36743deb1908b7b1b090bab8760
1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 # This script generates jit/LIROpsGenerated.h (list of LIR instructions)
6 # from LIROps.yaml.
8 import buildconfig
9 import six
10 import yaml
11 from mozbuild.preprocessor import Preprocessor
13 HEADER_TEMPLATE = """\
14 /* This Source Code Form is subject to the terms of the Mozilla Public
15 * License, v. 2.0. If a copy of the MPL was not distributed with this
16 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
18 #ifndef %(includeguard)s
19 #define %(includeguard)s
21 /* This file is generated by jit/GenerateLIRFiles.py. Do not edit! */
23 %(contents)s
25 #endif // %(includeguard)s
26 """
29 def load_yaml(yaml_path):
30 # First invoke preprocessor.py so that we can use #ifdef JS_SIMULATOR in
31 # the YAML file.
32 pp = Preprocessor()
33 pp.context.update(buildconfig.defines["ALLDEFINES"])
34 pp.out = six.StringIO()
35 pp.do_filter("substitution")
36 pp.do_include(yaml_path)
37 contents = pp.out.getvalue()
38 return yaml.safe_load(contents)
41 def generate_header(c_out, includeguard, contents):
42 c_out.write(
43 HEADER_TEMPLATE
44 % {
45 "includeguard": includeguard,
46 "contents": contents,
51 operand_types = {
52 "WordSized": "LAllocation",
53 "BoxedValue": "LBoxAllocation",
54 "Int64": "LInt64Allocation",
58 result_types = {
59 "WordSized": "1",
60 "BoxedValue": "BOX_PIECES",
61 "Int64": "INT64_PIECES",
65 def gen_helper_template_value(num_regular_allocs, num_value_allocs, num_int64_allocs):
66 template_str = ""
67 if num_value_allocs:
68 template_str += str(num_value_allocs) + " * BOX_PIECES + "
69 if num_int64_allocs:
70 template_str += str(num_int64_allocs) + " * INT64_PIECES + "
71 template_str += str(num_regular_allocs)
72 return template_str
75 def build_index_def(num_specials_operands, index_value, num_reg_operands, piece):
76 if num_specials_operands:
77 return " static const size_t {} = {} + {} * {};\\\n".format(
78 index_value, num_reg_operands, piece, num_specials_operands
80 else:
81 return " static const size_t {} = {};\\\n".format(
82 index_value, num_reg_operands
86 def gen_lir_class(
87 name, result_type, operands, arguments, num_temps, call_instruction, mir_op
89 """Generates class definition for a single LIR opcode."""
90 class_name = "L" + name
92 getters = []
93 setters = []
94 # Operand index definitions.
95 oper_indices = []
96 # Parameters for the class constructor.
97 constructor_params = []
99 num_reg_operands = 0
100 num_value_operands = 0
101 num_int64_operands = 0
102 if operands:
103 # Get number of LAllocations to use for defining indices.
104 for operand in operands:
105 if operands[operand] == "WordSized":
106 num_reg_operands += 1
108 current_reg_oper = 0
109 for operand in operands:
110 op_type = operands[operand]
111 op_alloc_type = operand_types[op_type]
112 constructor_params.append("const " + op_alloc_type + "& " + operand)
113 if op_type == "WordSized":
114 index_value = str(current_reg_oper)
115 current_reg_oper += 1
116 getters.append(
117 " const "
118 + op_alloc_type
119 + "* "
120 + operand
121 + "() { return getOperand("
122 + index_value
123 + "); }"
125 setters.append(" setOperand(" + index_value + ", " + operand + ");")
126 elif op_type == "BoxedValue":
127 index_value = operand[0].upper() + operand[1:] + "Index"
128 oper_indices.append(
129 build_index_def(
130 num_value_operands, index_value, num_reg_operands, "BOX_PIECES"
133 num_value_operands += 1
134 # No getters generated for BoxedValue operands.
135 setters.append(
136 " setBoxOperand(" + index_value + ", " + operand + ");"
138 elif op_type == "Int64":
139 index_value = operand[0].upper() + operand[1:] + "Index"
140 oper_indices.append(
141 build_index_def(
142 num_int64_operands,
143 index_value,
144 num_reg_operands,
145 "INT64_PIECES",
148 num_int64_operands += 1
149 getters.append(
150 " const "
151 + op_alloc_type
152 + " "
153 + operand
154 + "() { return getInt64Operand("
155 + index_value
156 + "); }"
158 setters.append(
159 " setInt64Operand(" + index_value + ", " + operand + ");"
161 else:
162 raise Exception("Invalid operand type: " + op_type)
163 if num_temps:
164 for temp in range(num_temps):
165 constructor_params.append("const LDefinition& temp" + str(temp))
166 setters.append(" setTemp(" + str(temp) + ", temp" + str(temp) + ");")
167 getters.append(
168 " const LDefinition* temp"
169 + str(temp)
170 + "() { return getTemp("
171 + str(temp)
172 + "); }"
174 code = "class {} : public LInstructionHelper<".format(class_name)
175 if result_type:
176 code += result_types[result_type] + ", "
177 else:
178 code += "0, "
179 code += gen_helper_template_value(
180 num_reg_operands, num_value_operands, num_int64_operands
182 code += ", {}> {{\\\n".format(num_temps)
183 if arguments:
184 for arg_name in arguments:
185 arg_type_sig = arguments[arg_name]
186 constructor_params.append(arg_type_sig + " " + arg_name)
187 code += " " + arg_type_sig + " " + arg_name + "_;\\\n"
188 code += " public:\\\n LIR_HEADER({})\\\n".format(name)
189 code += " explicit {}(".format(class_name)
190 code += ", ".join(constructor_params)
191 code += ") : LInstructionHelper(classOpcode)"
192 if arguments:
193 for arg_name in arguments:
194 code += ", " + arg_name + "_(" + arg_name + ")"
195 code += " {"
196 if call_instruction:
197 code += "\\\n this->setIsCall();"
198 code += "\\\n"
199 code += "\\\n".join(setters)
200 code += "\\\n }\\\n"
201 code += "\\\n".join(getters)
202 if arguments:
203 for arg_name in arguments:
204 code += " " + arguments[arg_name] + " " + arg_name + "() const { "
205 code += "return " + arg_name + "_; }\\\n"
206 code += "\\\n"
207 if operands:
208 code += "\\\n".join(oper_indices)
209 if mir_op:
210 if mir_op is True:
211 code += " M{}* mir() const {{ return mir_->to{}(); }};\\\n".format(
212 name, name
214 else:
215 code += " M{}* mir() const {{ return mir_->to{}(); }};\\\n".format(
216 mir_op, mir_op
218 code += "};\\\n"
219 return code
222 def generate_lir_header(c_out, yaml_path):
223 data = load_yaml(yaml_path)
225 # LIR_OPCODE_LIST opcode.
226 ops = []
228 # Generated LIR op class definitions.
229 lir_op_classes = []
231 for op in data:
232 name = op["name"]
234 gen_boilerplate = op.get("gen_boilerplate", True)
235 assert isinstance(gen_boilerplate, bool)
237 if gen_boilerplate:
238 result_type = op.get("result_type", None)
239 assert result_type is None or str
240 if result_type:
241 assert result_types[result_type]
243 operands = op.get("operands", None)
244 assert operands is None or isinstance(operands, dict)
246 arguments = op.get("arguments", None)
247 assert arguments is None or isinstance(arguments, dict)
249 num_temps = op.get("num_temps", 0)
250 assert num_temps is None or int
252 gen_boilerplate = op.get("gen_boilerplate", True)
253 assert isinstance(gen_boilerplate, bool)
255 call_instruction = op.get("call_instruction", None)
256 assert call_instruction is None or True
258 mir_op = op.get("mir_op", None)
259 assert mir_op is None or True or str
261 lir_op_classes.append(
262 gen_lir_class(
263 name,
264 result_type,
265 operands,
266 arguments,
267 num_temps,
268 call_instruction,
269 mir_op,
273 ops.append("_({})".format(name))
275 contents = "#define LIR_OPCODE_LIST(_)\\\n"
276 contents += "\\\n".join(ops)
277 contents += "\n\n"
279 contents += "#define LIR_OPCODE_CLASS_GENERATED \\\n"
280 contents += "\\\n".join(lir_op_classes)
281 contents += "\n\n"
283 generate_header(c_out, "jit_LIROpsGenerated_h", contents)