• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16// Autogenerated file -- DO NOT EDIT!
17
18template <Format format, typename It, typename... Types>
19static size_t Emit(It out, Types... args) { // NOLINT(readability-function-size)
20    size_t insn_len = 0;
21
22% insns_uniq_sort_fmts.each do |i| # Panda::formats.each do |fmt|
23%   fmt = i.format
24%   ops = i.operands
25%   offsets = [0]  # for opcode
26%   offsets += ops.map(&:offset).sort
27%   offsets += [fmt.size * 8]  # terminating offset, used for calculating last operand encoding width
28%
29    // Disable check due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203
30    // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
31    if constexpr (format == Format::<%= fmt.pretty.upcase %>) {
32        constexpr size_t SIZE = <%= fmt.size %>;
33        constexpr std::array<uint8_t, <%= offsets.size %>> OFF{<%= offsets.join(', ') %>};
34        static_assert(OFF.size() == sizeof...(args) + 1);
35        std::array<uint8_t, SIZE> buf{};
36        Span<uint8_t> buf_sp(buf);
37        Span<const uint8_t> off_sp(OFF);
38        EmitImpl(buf_sp, off_sp, args...);
39        std::copy(buf.begin(), buf.end(), out);
40        insn_len = SIZE;
41    }
42
43% end
44    return insn_len;
45}
46
47% OPCODE_TYPE = 'BytecodeInstruction::Opcode'
48% FORMAT_TYPE = 'BytecodeInstruction::Format'
49%
50% def opcode_full_name(i)
51%   OPCODE_TYPE + '::' + i.opcode.upcase
52% end
53%
54% def format_full_name(i)
55%   FORMAT_TYPE + '::' + i.format.pretty.upcase
56% end
57%
58% Panda::instructions.group_by(&:mnemonic).each do |mnemonic, group|
59%   emitter_name = group.first.emitter_name
60%   formats = group.map(&:format)
61%
62%   if emitter_name == "Jmp"
63%       next
64%   end
65%
66%   signature = emitter_signature(group, group.first.jump?)
67%   signature_str = signature.map { |o| "#{o.type} #{o.name}" }.join(', ')
68%
69// NOLINTNEXTLINE(misc-definitions-in-headers)
70void BytecodeEmitter::<%= emitter_name %>(<%= signature_str %>) {
71%
72%   method_args = signature.map(&:name)
73%   opcodes = group.map { |i| opcode_full_name(i) }
74%
75%   i = group[0]
76%
77%   if i.jcmpz?
78    Jcmpz(<%= opcodes[0] %>, <%= method_args.join(', ') %>);
79%   elsif i.jcmp?
80    Jcmp(<%= opcodes.join(', ') %>, <%= method_args.join(', ') %>);
81%   elsif group.length() == 1
82%       method_args_str = method_args.join(', ')
83%       if method_args_str != ''
84%           method_args_str = ', ' + method_args_str
85%       end
86%       format = format_full_name(i)
87%       opcode = opcode_full_name(i)
88    pc_ += Emit<<%= format %>>(std::back_inserter(bytecode_), <%= opcode %><%= method_args_str %>);
89%   else
90%       bitlen_vars = []
91%       signature.each do |arg|
92%           v = '%s_bitlen' % arg.name
93%           bitlen_vars.push(v)
94%           if arg.name.start_with?('imm')
95    auto <%= v %> = GetBitLengthSigned(<%= arg.name %>);
96%           else
97    auto <%= v %> = GetBitLengthUnsigned(<%= arg.name %>);
98%           end
99%       end
100%
101%       group.each do |i|
102%           conditions = []
103%           i.operands.each_with_index do |op, index|
104%               conditions.push("%s <= BitImmSize::BITSIZE_%d" % [bitlen_vars[index], op.width])
105%           end
106%           format = format_full_name(i)
107%           opcode = opcode_full_name(i)
108
109    if (<%= conditions.join(' && ') %>) {
110        pc_ += Emit<<%= format %>>(std::back_inserter(bytecode_), <%= opcode %>, <%= method_args.join(', ') %>);
111        return;
112    }
113%       end
114%   end
115}
116
117% end
118
119/* static */
120// NOLINTNEXTLINE(readability-function-size,misc-definitions-in-headers)
121size_t BytecodeEmitter::GetSizeByOpcode(<%= OPCODE_TYPE %> opcode) {
122    switch (opcode) {
123% Panda::instructions.each do |insn|
124    case <%= opcode_full_name(insn) %>:
125       return <%= insn.format.size %>;  // NOLINT(readability-magic-numbers)
126% end
127    default:
128        UNREACHABLE();
129        return 0;
130    }
131}
132
133/* static */
134// NOLINTNEXTLINE(misc-definitions-in-headers)
135BytecodeEmitter::BitImmSize BytecodeEmitter::GetBitImmSizeByOpcode(<%= OPCODE_TYPE %> opcode) {
136    switch (opcode) {
137% Panda::instructions.each do |insn|
138%   if insn.jump?
139    case <%= opcode_full_name(insn) %>:
140        return BytecodeEmitter::BitImmSize::BITSIZE_<%= insn.operands.select(&:imm?).first.width %>;
141%   end
142% end
143    default:
144        UNREACHABLE();
145        return BytecodeEmitter::BitImmSize::BITSIZE_32;  // Any return value will do, we are broken here anyway.
146    }
147}
148
149/* static */
150// NOLINTNEXTLINE(misc-definitions-in-headers)
151<%= OPCODE_TYPE %> BytecodeEmitter::RevertConditionCode(<%= OPCODE_TYPE %> opcode) {
152% CC_INVERTER = {
153%       "JEQ" => "JNE",
154%       "JNE" => "JEQ",
155%       "JLT" => "JGE",
156%       "JGE" => "JLT",
157%       "JGT" => "JLE",
158%       "JLE" => "JGT",
159% }
160    switch (opcode) {
161% Panda::instructions.each do |insn|
162%   if insn.conditional?
163    case <%= opcode_full_name(insn) %>:
164        return <%= OPCODE_TYPE %>::<%= insn.opcode.upcase.sub(/^.../, CC_INVERTER) %>;
165%   end
166% end
167    default:
168        UNREACHABLE();
169        return <%= OPCODE_TYPE %>::LAST;  // Any return value will do, we are broken here anyway.
170    }
171}
172
173/* static */
174// NOLINTNEXTLINE(misc-definitions-in-headers)
175<%= OPCODE_TYPE %> BytecodeEmitter::GetLongestConditionalJump(<%= OPCODE_TYPE %> opcode) {
176% JCC_WIDENER = {
177%       "_V8_IMM8" => "_V8_IMM16",
178%       "_V8_IMM16" => "_V8_IMM16",
179%       "_IMM8"     => "_IMM16",
180%       "_IMM16"    => "_IMM16",
181% }
182    switch (opcode) {
183% Panda::instructions.each do |insn|
184%   if insn.conditional?
185    case <%= OPCODE_TYPE %>::<%= insn.opcode.upcase %>:
186        return <%= OPCODE_TYPE %>::<%= insn.opcode.upcase.sub(/(_V4_IMM4|_V8_IMM16|_IMM8|_IMM16)$/, JCC_WIDENER) %>;
187%   end
188% end
189    default:
190        UNREACHABLE();
191        return <%= OPCODE_TYPE %>::LAST;  // Any return value will do, we are broken here anyway.
192    }
193}
194