RPNXCortado
C++23 JVM class-file, bytecode, validation, and JAR toolkit
Loading...
Searching...
No Matches
bytecode.hpp
Go to the documentation of this file.
1// AI Generated 2026 Ryan P. Nicholl <rnicholl@protonmail.com>
2// SPDX-License-Identifier: Apache-2.0
3
7
8#ifndef RPNX_CORTADO_BYTECODE_HPP
9#define RPNX_CORTADO_BYTECODE_HPP
10
11#include <array>
12#include <cstddef>
13#include <cstdint>
14#include <iterator>
17#include <span>
18#include <type_traits>
19#include <utility>
20#include <variant>
21#include <vector>
22
23namespace rpnx::cortado
24{
26 enum class processing_mode : std::uint8_t { strict, tooling };
27
30 {
31 std::uint16_t value{};
32 RPNX_MEMBER_METADATA(local_variable_index, value);
33 };
34
37 {
38 std::uint32_t value{};
39 RPNX_MEMBER_METADATA(code_offset, value);
40 };
41
44 {
45 std::int16_t value{};
46 RPNX_MEMBER_METADATA(branch_displacement16, value);
47 };
48
51 {
52 std::int32_t value{};
53 RPNX_MEMBER_METADATA(branch_displacement32, value);
54 };
55
57 enum class newarray_type : std::uint8_t { boolean = 4, character = 5, floating_point = 6, double_precision = 7, byte = 8, short_integer = 9, integer = 10, long_integer = 11 };
58
60 enum class opcode : std::uint8_t { nop = 0x00, aconst_null = 0x01, iconst_m1 = 0x02, iconst_0 = 0x03, iconst_1 = 0x04, iconst_2 = 0x05, iconst_3 = 0x06, iconst_4 = 0x07, iconst_5 = 0x08, lconst_0 = 0x09, lconst_1 = 0x0A, fconst_0 = 0x0B, fconst_1 = 0x0C, fconst_2 = 0x0D, dconst_0 = 0x0E, dconst_1 = 0x0F, bipush = 0x10, sipush = 0x11, ldc = 0x12, ldc_w = 0x13, ldc2_w = 0x14, iload = 0x15, lload = 0x16, fload = 0x17, dload = 0x18, aload = 0x19, iload_0 = 0x1A, iload_1 = 0x1B, iload_2 = 0x1C, iload_3 = 0x1D, lload_0 = 0x1E, lload_1 = 0x1F, lload_2 = 0x20, lload_3 = 0x21, fload_0 = 0x22, fload_1 = 0x23, fload_2 = 0x24, fload_3 = 0x25, dload_0 = 0x26, dload_1 = 0x27, dload_2 = 0x28, dload_3 = 0x29, aload_0 = 0x2A, aload_1 = 0x2B, aload_2 = 0x2C, aload_3 = 0x2D, iaload = 0x2E, laload = 0x2F, faload = 0x30, daload = 0x31, aaload = 0x32, baload = 0x33, caload = 0x34, saload = 0x35, istore = 0x36, lstore = 0x37, fstore = 0x38, dstore = 0x39, astore = 0x3A, istore_0 = 0x3B, istore_1 = 0x3C, istore_2 = 0x3D, istore_3 = 0x3E, lstore_0 = 0x3F, lstore_1 = 0x40, lstore_2 = 0x41, lstore_3 = 0x42, fstore_0 = 0x43, fstore_1 = 0x44, fstore_2 = 0x45, fstore_3 = 0x46, dstore_0 = 0x47, dstore_1 = 0x48, dstore_2 = 0x49, dstore_3 = 0x4A, astore_0 = 0x4B, astore_1 = 0x4C, astore_2 = 0x4D, astore_3 = 0x4E, iastore = 0x4F, lastore = 0x50, fastore = 0x51, dastore = 0x52, aastore = 0x53, bastore = 0x54, castore = 0x55, sastore = 0x56, pop = 0x57, pop2 = 0x58, dup = 0x59, dup_x1 = 0x5A, dup_x2 = 0x5B, dup2 = 0x5C, dup2_x1 = 0x5D, dup2_x2 = 0x5E, swap = 0x5F, iadd = 0x60, ladd = 0x61, fadd = 0x62, dadd = 0x63, isub = 0x64, lsub = 0x65, fsub = 0x66, dsub = 0x67, imul = 0x68, lmul = 0x69, fmul = 0x6A, dmul = 0x6B, idiv = 0x6C, ldiv = 0x6D, fdiv = 0x6E, ddiv = 0x6F, irem = 0x70, lrem = 0x71, frem = 0x72, drem = 0x73, ineg = 0x74, lneg = 0x75, fneg = 0x76, dneg = 0x77, ishl = 0x78, lshl = 0x79, ishr = 0x7A, lshr = 0x7B, iushr = 0x7C, lushr = 0x7D, iand = 0x7E, land = 0x7F, ior = 0x80, lor = 0x81, ixor = 0x82, lxor = 0x83, iinc = 0x84, i2l = 0x85, i2f = 0x86, i2d = 0x87, l2i = 0x88, l2f = 0x89, l2d = 0x8A, f2i = 0x8B, f2l = 0x8C, f2d = 0x8D, d2i = 0x8E, d2l = 0x8F, d2f = 0x90, i2b = 0x91, i2c = 0x92, i2s = 0x93, lcmp = 0x94, fcmpl = 0x95, fcmpg = 0x96, dcmpl = 0x97, dcmpg = 0x98, ifeq = 0x99, ifne = 0x9A, iflt = 0x9B, ifge = 0x9C, ifgt = 0x9D, ifle = 0x9E, if_icmpeq = 0x9F, if_icmpne = 0xA0, if_icmplt = 0xA1, if_icmpge = 0xA2, if_icmpgt = 0xA3, if_icmple = 0xA4, if_acmpeq = 0xA5, if_acmpne = 0xA6, goto_ = 0xA7, jsr = 0xA8, ret = 0xA9, tableswitch = 0xAA, lookupswitch = 0xAB, ireturn = 0xAC, lreturn = 0xAD, freturn = 0xAE, dreturn = 0xAF, areturn = 0xB0, return_ = 0xB1, getstatic = 0xB2, putstatic = 0xB3, getfield = 0xB4, putfield = 0xB5, invokevirtual = 0xB6, invokespecial = 0xB7, invokestatic = 0xB8, invokeinterface = 0xB9, invokedynamic = 0xBA, new_ = 0xBB, newarray = 0xBC, anewarray = 0xBD, arraylength = 0xBE, athrow = 0xBF, checkcast = 0xC0, instanceof_ = 0xC1, monitorenter = 0xC2, monitorexit = 0xC3, wide = 0xC4, multianewarray = 0xC5, ifnull = 0xC6, ifnonnull = 0xC7, goto_w = 0xC8, jsr_w = 0xC9, breakpoint = 0xCA, impdep1 = 0xFE, impdep2 = 0xFF };
61
63 template < opcode Operation >
65 {
66 static constexpr opcode operation = Operation;
67 RPNX_EMPTY_METADATA(simple_instruction);
68 };
69
71 template < opcode Operation >
73 {
74 static constexpr opcode operation = Operation;
75 std::int8_t value{};
76 RPNX_MEMBER_METADATA(signed_byte_instruction, value);
77 };
78
80 template < opcode Operation >
82 {
83 static constexpr opcode operation = Operation;
84 std::int16_t value{};
85 RPNX_MEMBER_METADATA(signed_short_instruction, value);
86 };
87
89 template < opcode Operation >
91 {
92 static constexpr opcode operation = Operation;
93 std::uint8_t index{};
94 RPNX_MEMBER_METADATA(constant_pool_index8_instruction, index);
95 };
96
98 template < opcode Operation >
100 {
101 static constexpr opcode operation = Operation;
103 RPNX_MEMBER_METADATA(constant_pool_index16_instruction, index);
104 };
105
107 template < opcode Operation >
109 {
110 static constexpr opcode operation = Operation;
111 std::uint8_t index{};
112 RPNX_MEMBER_METADATA(local_instruction, index);
113 };
114
116 template < opcode Operation >
118 {
119 static constexpr opcode operation = Operation;
121 RPNX_MEMBER_METADATA(branch16_instruction, displacement);
122 };
123
125 template < opcode Operation >
127 {
128 static constexpr opcode operation = Operation;
130 RPNX_MEMBER_METADATA(branch32_instruction, displacement);
131 };
132
135 {
136 static constexpr opcode operation = opcode::iinc;
137 std::uint8_t index{};
138 std::int8_t amount{};
139 RPNX_MEMBER_METADATA(iinc_instruction, index, amount);
140 };
141
143 template < opcode ModifiedOperation >
145 {
146 static constexpr opcode modified_operation = ModifiedOperation;
148 RPNX_MEMBER_METADATA(wide_local_instruction, index);
149 };
150
153 {
155 std::int16_t amount{};
156 RPNX_MEMBER_METADATA(wide_iinc_instruction, index, amount);
157 };
158
161
164 {
165 static constexpr opcode operation = opcode::wide;
167 RPNX_MEMBER_METADATA(wide_instruction, operand);
168 };
169
172 {
173 std::int32_t match{};
175 RPNX_MEMBER_METADATA(lookup_switch_pair, match, displacement);
176 };
177
180 {
181 static constexpr opcode operation = opcode::tableswitch;
182 std::vector< std::byte > padding;
184 std::int32_t low{};
185 std::vector< branch_displacement32 > displacements;
187 };
188
191 {
192 static constexpr opcode operation = opcode::lookupswitch;
193 std::vector< std::byte > padding;
195 std::vector< lookup_switch_pair > pairs;
197 };
198
201 {
202 static constexpr opcode operation = opcode::invokeinterface;
204 std::uint8_t count{};
205 std::uint8_t reserved{};
206 RPNX_MEMBER_METADATA(invokeinterface_instruction, index, count, reserved);
207 };
208
211 {
212 static constexpr opcode operation = opcode::invokedynamic;
214 std::uint16_t reserved{};
215 RPNX_MEMBER_METADATA(invokedynamic_instruction, index, reserved);
216 };
217
220 {
221 static constexpr opcode operation = opcode::newarray;
222 newarray_type element_type{newarray_type::integer};
223 RPNX_MEMBER_METADATA(newarray_instruction, element_type);
224 };
225
228 {
229 static constexpr opcode operation = opcode::multianewarray;
231 std::uint8_t dimensions{};
232 RPNX_MEMBER_METADATA(multianewarray_instruction, index, dimensions);
233 };
234
236 using instruction = std::variant< simple_instruction< opcode::nop >, simple_instruction< opcode::aconst_null >, simple_instruction< opcode::iconst_m1 >, simple_instruction< opcode::iconst_0 >, simple_instruction< opcode::iconst_1 >, simple_instruction< opcode::iconst_2 >, simple_instruction< opcode::iconst_3 >, simple_instruction< opcode::iconst_4 >, simple_instruction< opcode::iconst_5 >, simple_instruction< opcode::lconst_0 >, simple_instruction< opcode::lconst_1 >, simple_instruction< opcode::fconst_0 >, simple_instruction< opcode::fconst_1 >, simple_instruction< opcode::fconst_2 >, simple_instruction< opcode::dconst_0 >, simple_instruction< opcode::dconst_1 >, signed_byte_instruction< opcode::bipush >, signed_short_instruction< opcode::sipush >, constant_pool_index8_instruction< opcode::ldc >, constant_pool_index16_instruction< opcode::ldc_w >, constant_pool_index16_instruction< opcode::ldc2_w >, local_instruction< opcode::iload >, local_instruction< opcode::lload >, local_instruction< opcode::fload >, local_instruction< opcode::dload >, local_instruction< opcode::aload >, simple_instruction< opcode::iload_0 >, simple_instruction< opcode::iload_1 >, simple_instruction< opcode::iload_2 >, simple_instruction< opcode::iload_3 >, simple_instruction< opcode::lload_0 >, simple_instruction< opcode::lload_1 >, simple_instruction< opcode::lload_2 >, simple_instruction< opcode::lload_3 >, simple_instruction< opcode::fload_0 >, simple_instruction< opcode::fload_1 >, simple_instruction< opcode::fload_2 >, simple_instruction< opcode::fload_3 >, simple_instruction< opcode::dload_0 >, simple_instruction< opcode::dload_1 >, simple_instruction< opcode::dload_2 >, simple_instruction< opcode::dload_3 >, simple_instruction< opcode::aload_0 >, simple_instruction< opcode::aload_1 >, simple_instruction< opcode::aload_2 >, simple_instruction< opcode::aload_3 >, simple_instruction< opcode::iaload >, simple_instruction< opcode::laload >, simple_instruction< opcode::faload >, simple_instruction< opcode::daload >, simple_instruction< opcode::aaload >, simple_instruction< opcode::baload >, simple_instruction< opcode::caload >, simple_instruction< opcode::saload >, local_instruction< opcode::istore >, local_instruction< opcode::lstore >, local_instruction< opcode::fstore >, local_instruction< opcode::dstore >, local_instruction< opcode::astore >, simple_instruction< opcode::istore_0 >, simple_instruction< opcode::istore_1 >, simple_instruction< opcode::istore_2 >, simple_instruction< opcode::istore_3 >, simple_instruction< opcode::lstore_0 >, simple_instruction< opcode::lstore_1 >, simple_instruction< opcode::lstore_2 >, simple_instruction< opcode::lstore_3 >, simple_instruction< opcode::fstore_0 >, simple_instruction< opcode::fstore_1 >, simple_instruction< opcode::fstore_2 >, simple_instruction< opcode::fstore_3 >, simple_instruction< opcode::dstore_0 >, simple_instruction< opcode::dstore_1 >, simple_instruction< opcode::dstore_2 >, simple_instruction< opcode::dstore_3 >, simple_instruction< opcode::astore_0 >, simple_instruction< opcode::astore_1 >, simple_instruction< opcode::astore_2 >, simple_instruction< opcode::astore_3 >, simple_instruction< opcode::iastore >, simple_instruction< opcode::lastore >, simple_instruction< opcode::fastore >, simple_instruction< opcode::dastore >, simple_instruction< opcode::aastore >, simple_instruction< opcode::bastore >, simple_instruction< opcode::castore >, simple_instruction< opcode::sastore >, simple_instruction< opcode::pop >, simple_instruction< opcode::pop2 >, simple_instruction< opcode::dup >, simple_instruction< opcode::dup_x1 >, simple_instruction< opcode::dup_x2 >, simple_instruction< opcode::dup2 >, simple_instruction< opcode::dup2_x1 >, simple_instruction< opcode::dup2_x2 >, simple_instruction< opcode::swap >, simple_instruction< opcode::iadd >, simple_instruction< opcode::ladd >, simple_instruction< opcode::fadd >, simple_instruction< opcode::dadd >, simple_instruction< opcode::isub >, simple_instruction< opcode::lsub >, simple_instruction< opcode::fsub >, simple_instruction< opcode::dsub >, simple_instruction< opcode::imul >, simple_instruction< opcode::lmul >, simple_instruction< opcode::fmul >, simple_instruction< opcode::dmul >, simple_instruction< opcode::idiv >, simple_instruction< opcode::ldiv >, simple_instruction< opcode::fdiv >, simple_instruction< opcode::ddiv >, simple_instruction< opcode::irem >, simple_instruction< opcode::lrem >, simple_instruction< opcode::frem >, simple_instruction< opcode::drem >, simple_instruction< opcode::ineg >, simple_instruction< opcode::lneg >, simple_instruction< opcode::fneg >, simple_instruction< opcode::dneg >, simple_instruction< opcode::ishl >, simple_instruction< opcode::lshl >, simple_instruction< opcode::ishr >, simple_instruction< opcode::lshr >, simple_instruction< opcode::iushr >, simple_instruction< opcode::lushr >, simple_instruction< opcode::iand >, simple_instruction< opcode::land >, simple_instruction< opcode::ior >, simple_instruction< opcode::lor >, simple_instruction< opcode::ixor >, simple_instruction< opcode::lxor >, iinc_instruction, simple_instruction< opcode::i2l >, simple_instruction< opcode::i2f >, simple_instruction< opcode::i2d >, simple_instruction< opcode::l2i >, simple_instruction< opcode::l2f >, simple_instruction< opcode::l2d >, simple_instruction< opcode::f2i >, simple_instruction< opcode::f2l >, simple_instruction< opcode::f2d >, simple_instruction< opcode::d2i >, simple_instruction< opcode::d2l >, simple_instruction< opcode::d2f >, simple_instruction< opcode::i2b >, simple_instruction< opcode::i2c >, simple_instruction< opcode::i2s >, simple_instruction< opcode::lcmp >, simple_instruction< opcode::fcmpl >, simple_instruction< opcode::fcmpg >, simple_instruction< opcode::dcmpl >, simple_instruction< opcode::dcmpg >, branch16_instruction< opcode::ifeq >, branch16_instruction< opcode::ifne >, branch16_instruction< opcode::iflt >, branch16_instruction< opcode::ifge >, branch16_instruction< opcode::ifgt >, branch16_instruction< opcode::ifle >, branch16_instruction< opcode::if_icmpeq >, branch16_instruction< opcode::if_icmpne >, branch16_instruction< opcode::if_icmplt >, branch16_instruction< opcode::if_icmpge >, branch16_instruction< opcode::if_icmpgt >, branch16_instruction< opcode::if_icmple >, branch16_instruction< opcode::if_acmpeq >, branch16_instruction< opcode::if_acmpne >, branch16_instruction< opcode::goto_ >, branch16_instruction< opcode::jsr >, local_instruction< opcode::ret >, tableswitch_instruction, lookupswitch_instruction, simple_instruction< opcode::ireturn >, simple_instruction< opcode::lreturn >, simple_instruction< opcode::freturn >, simple_instruction< opcode::dreturn >, simple_instruction< opcode::areturn >, simple_instruction< opcode::return_ >, constant_pool_index16_instruction< opcode::getstatic >, constant_pool_index16_instruction< opcode::putstatic >, constant_pool_index16_instruction< opcode::getfield >, constant_pool_index16_instruction< opcode::putfield >, constant_pool_index16_instruction< opcode::invokevirtual >, constant_pool_index16_instruction< opcode::invokespecial >, constant_pool_index16_instruction< opcode::invokestatic >, invokeinterface_instruction, invokedynamic_instruction, constant_pool_index16_instruction< opcode::new_ >, newarray_instruction, constant_pool_index16_instruction< opcode::anewarray >, simple_instruction< opcode::arraylength >, simple_instruction< opcode::athrow >, constant_pool_index16_instruction< opcode::checkcast >, constant_pool_index16_instruction< opcode::instanceof_ >, simple_instruction< opcode::monitorenter >, simple_instruction< opcode::monitorexit >, wide_instruction, multianewarray_instruction, branch16_instruction< opcode::ifnull >, branch16_instruction< opcode::ifnonnull >, branch32_instruction< opcode::goto_w >, branch32_instruction< opcode::jsr_w >, simple_instruction< opcode::breakpoint >, simple_instruction< opcode::impdep1 >, simple_instruction< opcode::impdep2 > >;
237
238 namespace bytecode_model_detail
239 {
240 template < std::size_t... Indexes >
241 [[nodiscard]] consteval bool has_complete_unique_opcode_coverage(std::index_sequence< Indexes... >)
242 {
243 std::array< bool, 256 > seen{};
244 bool unique = true;
245 auto record = [&](opcode operation)
246 {
247 std::size_t const value = static_cast< std::uint8_t >(operation);
248 if (seen[value])
249 {
250 unique = false;
251 }
252 seen[value] = true;
253 };
254 (record(std::variant_alternative_t< Indexes, instruction >::operation), ...);
255 if (!unique)
256 {
257 return false;
258 }
259 for (std::size_t value = 0; value <= static_cast< std::uint8_t >(opcode::breakpoint); ++value)
260 {
261 if (!seen[value])
262 {
263 return false;
264 }
265 }
266 return seen[static_cast< std::uint8_t >(opcode::impdep1)] && seen[static_cast< std::uint8_t >(opcode::impdep2)];
267 }
268 } // namespace bytecode_model_detail
269
270 static_assert(std::variant_size_v< instruction > == 205, "the instruction variant must contain every defined and reserved JVM opcode exactly once");
271 static_assert(bytecode_model_detail::has_complete_unique_opcode_coverage(std::make_index_sequence< std::variant_size_v< instruction > >{}), "the instruction variant has an omitted or duplicate JVM opcode");
272
279 template < typename Visitor >
280 [[nodiscard]] bool visit_instruction_type(opcode operation, Visitor&& visitor)
281 {
282 using visitor_type = std::remove_reference_t< Visitor >;
283 using callback = void (*)(visitor_type&);
284 static constexpr std::array< callback, 256 > callbacks = []< std::size_t... Indexes >(std::index_sequence< Indexes... >)
285 {
286 std::array< callback, 256 > result{};
287 ((result[static_cast< std::uint8_t >(std::variant_alternative_t< Indexes, instruction >::operation)] = [](visitor_type& value)
288 { value(std::type_identity< std::variant_alternative_t< Indexes, instruction > >{}); }),
289 ...);
290 return result;
291 }(std::make_index_sequence< std::variant_size_v< instruction > >{});
292
293 callback const selected = callbacks[static_cast< std::uint8_t >(operation)];
294 if (selected == nullptr)
295 {
296 return false;
297 }
298 selected(visitor);
299 return true;
300 }
301
304 {
305 std::vector< instruction > instructions;
306 RPNX_MEMBER_METADATA(instruction_sequence, instructions);
307 };
308
310 struct raw_code
311 {
312 std::vector< std::byte > bytes;
313 RPNX_MEMBER_METADATA(raw_code, bytes);
314 };
315
317 using code_body = std::variant< instruction_sequence, raw_code >;
318
321 {
322 processing_mode mode{processing_mode::strict};
323 std::size_t maximum_code_length{65535};
324 RPNX_MEMBER_METADATA(bytecode_read_options, mode, maximum_code_length);
325 };
326
329 {
330 processing_mode mode{processing_mode::strict};
331 RPNX_MEMBER_METADATA(bytecode_write_options, mode);
332 };
333
338 [[nodiscard]] opcode instruction_opcode(instruction const& value) noexcept;
339
345 [[nodiscard]] std::size_t instruction_size(instruction const& value, code_offset offset);
346
353 [[nodiscard]] code_body deserialize_instructions(std::span< std::byte const > bytes, bytecode_read_options const& options = {});
354
361 [[nodiscard]] std::vector< std::byte > serialize_instructions(code_body const& value, bytecode_write_options const& options = {});
362
370 template < typename OutputIt >
371 auto serialize_iter(code_body const& value, OutputIt output, bytecode_write_options const& options = {}) -> OutputIt
372 {
373 std::vector< std::byte > const bytes = serialize_instructions(value, options);
374 for (std::byte const byte : bytes)
375 {
376 *output = byte;
377 ++output;
378 }
379 return output;
380 }
381
391 template < typename OutputIt >
392 auto serialize_iter(code_body const& value, OutputIt output, OutputIt end, bytecode_write_options const& options = {}) -> OutputIt
393 {
394 std::vector< std::byte > const bytes = serialize_instructions(value, options);
395 for (std::byte const byte : bytes)
396 {
397 if (output == end)
398 {
399 throw std::length_error("output range is too small for the JVM code array");
400 }
401 *output = byte;
402 ++output;
403 }
404 return output;
405 }
406
416 template < std::forward_iterator InputIt, std::sentinel_for< InputIt > Sentinel >
417 auto deserialize_iter(code_body& value, InputIt input, Sentinel end, bytecode_read_options const& options = {}) -> InputIt
418 {
419 std::vector< std::byte > bytes;
420 for (InputIt cursor = input; cursor != end; ++cursor)
421 {
422 bytes.push_back(static_cast< std::byte >(*cursor));
423 }
424 value = deserialize_instructions(bytes, options);
425 while (input != end)
426 {
427 ++input;
428 }
429 return input;
430 }
431} // namespace rpnx::cortado
432
433#endif // RPNX_CORTADO_BYTECODE_HPP
Exception types used by parsing, validation, and assembly APIs.
JVM class-file, bytecode, validation, generation, and JAR APIs.
processing_mode
Controls whether invalid-but-preservable tool input is accepted.
Definition bytecode.hpp:26
std::variant< instruction_sequence, raw_code > code_body
Either a decoded instruction sequence or an exact raw tooling payload.
Definition bytecode.hpp:317
std::variant< simple_instruction< opcode::nop >, simple_instruction< opcode::aconst_null >, simple_instruction< opcode::iconst_m1 >, simple_instruction< opcode::iconst_0 >, simple_instruction< opcode::iconst_1 >, simple_instruction< opcode::iconst_2 >, simple_instruction< opcode::iconst_3 >, simple_instruction< opcode::iconst_4 >, simple_instruction< opcode::iconst_5 >, simple_instruction< opcode::lconst_0 >, simple_instruction< opcode::lconst_1 >, simple_instruction< opcode::fconst_0 >, simple_instruction< opcode::fconst_1 >, simple_instruction< opcode::fconst_2 >, simple_instruction< opcode::dconst_0 >, simple_instruction< opcode::dconst_1 >, signed_byte_instruction< opcode::bipush >, signed_short_instruction< opcode::sipush >, constant_pool_index8_instruction< opcode::ldc >, constant_pool_index16_instruction< opcode::ldc_w >, constant_pool_index16_instruction< opcode::ldc2_w >, local_instruction< opcode::iload >, local_instruction< opcode::lload >, local_instruction< opcode::fload >, local_instruction< opcode::dload >, local_instruction< opcode::aload >, simple_instruction< opcode::iload_0 >, simple_instruction< opcode::iload_1 >, simple_instruction< opcode::iload_2 >, simple_instruction< opcode::iload_3 >, simple_instruction< opcode::lload_0 >, simple_instruction< opcode::lload_1 >, simple_instruction< opcode::lload_2 >, simple_instruction< opcode::lload_3 >, simple_instruction< opcode::fload_0 >, simple_instruction< opcode::fload_1 >, simple_instruction< opcode::fload_2 >, simple_instruction< opcode::fload_3 >, simple_instruction< opcode::dload_0 >, simple_instruction< opcode::dload_1 >, simple_instruction< opcode::dload_2 >, simple_instruction< opcode::dload_3 >, simple_instruction< opcode::aload_0 >, simple_instruction< opcode::aload_1 >, simple_instruction< opcode::aload_2 >, simple_instruction< opcode::aload_3 >, simple_instruction< opcode::iaload >, simple_instruction< opcode::laload >, simple_instruction< opcode::faload >, simple_instruction< opcode::daload >, simple_instruction< opcode::aaload >, simple_instruction< opcode::baload >, simple_instruction< opcode::caload >, simple_instruction< opcode::saload >, local_instruction< opcode::istore >, local_instruction< opcode::lstore >, local_instruction< opcode::fstore >, local_instruction< opcode::dstore >, local_instruction< opcode::astore >, simple_instruction< opcode::istore_0 >, simple_instruction< opcode::istore_1 >, simple_instruction< opcode::istore_2 >, simple_instruction< opcode::istore_3 >, simple_instruction< opcode::lstore_0 >, simple_instruction< opcode::lstore_1 >, simple_instruction< opcode::lstore_2 >, simple_instruction< opcode::lstore_3 >, simple_instruction< opcode::fstore_0 >, simple_instruction< opcode::fstore_1 >, simple_instruction< opcode::fstore_2 >, simple_instruction< opcode::fstore_3 >, simple_instruction< opcode::dstore_0 >, simple_instruction< opcode::dstore_1 >, simple_instruction< opcode::dstore_2 >, simple_instruction< opcode::dstore_3 >, simple_instruction< opcode::astore_0 >, simple_instruction< opcode::astore_1 >, simple_instruction< opcode::astore_2 >, simple_instruction< opcode::astore_3 >, simple_instruction< opcode::iastore >, simple_instruction< opcode::lastore >, simple_instruction< opcode::fastore >, simple_instruction< opcode::dastore >, simple_instruction< opcode::aastore >, simple_instruction< opcode::bastore >, simple_instruction< opcode::castore >, simple_instruction< opcode::sastore >, simple_instruction< opcode::pop >, simple_instruction< opcode::pop2 >, simple_instruction< opcode::dup >, simple_instruction< opcode::dup_x1 >, simple_instruction< opcode::dup_x2 >, simple_instruction< opcode::dup2 >, simple_instruction< opcode::dup2_x1 >, simple_instruction< opcode::dup2_x2 >, simple_instruction< opcode::swap >, simple_instruction< opcode::iadd >, simple_instruction< opcode::ladd >, simple_instruction< opcode::fadd >, simple_instruction< opcode::dadd >, simple_instruction< opcode::isub >, simple_instruction< opcode::lsub >, simple_instruction< opcode::fsub >, simple_instruction< opcode::dsub >, simple_instruction< opcode::imul >, simple_instruction< opcode::lmul >, simple_instruction< opcode::fmul >, simple_instruction< opcode::dmul >, simple_instruction< opcode::idiv >, simple_instruction< opcode::ldiv >, simple_instruction< opcode::fdiv >, simple_instruction< opcode::ddiv >, simple_instruction< opcode::irem >, simple_instruction< opcode::lrem >, simple_instruction< opcode::frem >, simple_instruction< opcode::drem >, simple_instruction< opcode::ineg >, simple_instruction< opcode::lneg >, simple_instruction< opcode::fneg >, simple_instruction< opcode::dneg >, simple_instruction< opcode::ishl >, simple_instruction< opcode::lshl >, simple_instruction< opcode::ishr >, simple_instruction< opcode::lshr >, simple_instruction< opcode::iushr >, simple_instruction< opcode::lushr >, simple_instruction< opcode::iand >, simple_instruction< opcode::land >, simple_instruction< opcode::ior >, simple_instruction< opcode::lor >, simple_instruction< opcode::ixor >, simple_instruction< opcode::lxor >, iinc_instruction, simple_instruction< opcode::i2l >, simple_instruction< opcode::i2f >, simple_instruction< opcode::i2d >, simple_instruction< opcode::l2i >, simple_instruction< opcode::l2f >, simple_instruction< opcode::l2d >, simple_instruction< opcode::f2i >, simple_instruction< opcode::f2l >, simple_instruction< opcode::f2d >, simple_instruction< opcode::d2i >, simple_instruction< opcode::d2l >, simple_instruction< opcode::d2f >, simple_instruction< opcode::i2b >, simple_instruction< opcode::i2c >, simple_instruction< opcode::i2s >, simple_instruction< opcode::lcmp >, simple_instruction< opcode::fcmpl >, simple_instruction< opcode::fcmpg >, simple_instruction< opcode::dcmpl >, simple_instruction< opcode::dcmpg >, branch16_instruction< opcode::ifeq >, branch16_instruction< opcode::ifne >, branch16_instruction< opcode::iflt >, branch16_instruction< opcode::ifge >, branch16_instruction< opcode::ifgt >, branch16_instruction< opcode::ifle >, branch16_instruction< opcode::if_icmpeq >, branch16_instruction< opcode::if_icmpne >, branch16_instruction< opcode::if_icmplt >, branch16_instruction< opcode::if_icmpge >, branch16_instruction< opcode::if_icmpgt >, branch16_instruction< opcode::if_icmple >, branch16_instruction< opcode::if_acmpeq >, branch16_instruction< opcode::if_acmpne >, branch16_instruction< opcode::goto_ >, branch16_instruction< opcode::jsr >, local_instruction< opcode::ret >, tableswitch_instruction, lookupswitch_instruction, simple_instruction< opcode::ireturn >, simple_instruction< opcode::lreturn >, simple_instruction< opcode::freturn >, simple_instruction< opcode::dreturn >, simple_instruction< opcode::areturn >, simple_instruction< opcode::return_ >, constant_pool_index16_instruction< opcode::getstatic >, constant_pool_index16_instruction< opcode::putstatic >, constant_pool_index16_instruction< opcode::getfield >, constant_pool_index16_instruction< opcode::putfield >, constant_pool_index16_instruction< opcode::invokevirtual >, constant_pool_index16_instruction< opcode::invokespecial >, constant_pool_index16_instruction< opcode::invokestatic >, invokeinterface_instruction, invokedynamic_instruction, constant_pool_index16_instruction< opcode::new_ >, newarray_instruction, constant_pool_index16_instruction< opcode::anewarray >, simple_instruction< opcode::arraylength >, simple_instruction< opcode::athrow >, constant_pool_index16_instruction< opcode::checkcast >, constant_pool_index16_instruction< opcode::instanceof_ >, simple_instruction< opcode::monitorenter >, simple_instruction< opcode::monitorexit >, wide_instruction, multianewarray_instruction, branch16_instruction< opcode::ifnull >, branch16_instruction< opcode::ifnonnull >, branch32_instruction< opcode::goto_w >, branch32_instruction< opcode::jsr_w >, simple_instruction< opcode::breakpoint >, simple_instruction< opcode::impdep1 >, simple_instruction< opcode::impdep2 > > instruction
Every exact JVM instruction encoding supported by Java SE 26.
Definition bytecode.hpp:236
std::size_t instruction_size(instruction const &value, code_offset offset)
Returns the exact encoded size of an instruction at the supplied byte offset.
bool visit_instruction_type(opcode operation, Visitor &&visitor)
Invokes a visitor with the instruction type associated with a runtime opcode.
Definition bytecode.hpp:280
std::variant< wide_local_instruction< opcode::iload >, wide_local_instruction< opcode::lload >, wide_local_instruction< opcode::fload >, wide_local_instruction< opcode::dload >, wide_local_instruction< opcode::aload >, wide_local_instruction< opcode::istore >, wide_local_instruction< opcode::lstore >, wide_local_instruction< opcode::fstore >, wide_local_instruction< opcode::dstore >, wide_local_instruction< opcode::astore >, wide_local_instruction< opcode::ret >, wide_iinc_instruction > wide_operand
Exact operand of a wide-prefixed instruction.
Definition bytecode.hpp:160
opcode instruction_opcode(instruction const &value) noexcept
Returns the opcode of a structured instruction.
opcode
Every defined Java SE 26 opcode, plus the three permanently reserved opcodes.
Definition bytecode.hpp:60
code_body deserialize_instructions(std::span< std::byte const > bytes, bytecode_read_options const &options={})
Decodes an entire JVM code array.
newarray_type
Primitive array types accepted by the newarray instruction.
Definition bytecode.hpp:57
auto serialize_iter(code_body const &value, OutputIt output, bytecode_write_options const &options={}) -> OutputIt
Serial4-style bytecode output-iterator interface.
Definition bytecode.hpp:371
std::vector< std::byte > serialize_instructions(code_body const &value, bytecode_write_options const &options={})
Encodes an entire JVM code array.
auto deserialize_iter(code_body &value, InputIt input, Sentinel end, bytecode_read_options const &options={}) -> InputIt
Serial4-style bytecode forward-iterator interface.
Definition bytecode.hpp:417
A two-byte branch instruction.
Definition bytecode.hpp:118
branch_displacement16 displacement
Target displacement relative to this instruction's opcode.
Definition bytecode.hpp:120
A four-byte branch instruction.
Definition bytecode.hpp:127
branch_displacement32 displacement
Target displacement relative to this instruction's opcode.
Definition bytecode.hpp:129
A signed 16-bit branch displacement relative to an instruction opcode.
Definition bytecode.hpp:44
std::int16_t value
Signed bytes from the branch opcode to its target opcode.
Definition bytecode.hpp:45
A signed 32-bit branch displacement relative to an instruction opcode.
Definition bytecode.hpp:51
std::int32_t value
Signed bytes from the branch opcode to its target opcode.
Definition bytecode.hpp:52
Resource and strictness controls for bytecode decoding.
Definition bytecode.hpp:321
std::size_t maximum_code_length
Maximum bytes accepted, additionally capped by the JVM limit.
Definition bytecode.hpp:323
processing_mode mode
Strict rejection or raw-code tooling fallback.
Definition bytecode.hpp:322
Strictness controls for bytecode encoding.
Definition bytecode.hpp:329
processing_mode mode
Strict rejection or exact raw/reserved tooling output.
Definition bytecode.hpp:330
A byte offset within the code array of a Code attribute.
Definition bytecode.hpp:37
std::uint32_t value
Byte offset from the first opcode in the enclosing code array.
Definition bytecode.hpp:38
A two-byte constant-pool-index instruction.
Definition bytecode.hpp:100
constant_pool_index index
Two-byte logical constant-pool index.
Definition bytecode.hpp:102
A one-byte constant-pool-index instruction.
Definition bytecode.hpp:91
std::uint8_t index
Nonzero one-byte constant-pool index.
Definition bytecode.hpp:93
A type-safe index into a JVM constant pool.
Definition types.hpp:34
The compact iinc instruction.
Definition bytecode.hpp:135
std::int8_t amount
Signed increment.
Definition bytecode.hpp:138
std::uint8_t index
Local int slot to update.
Definition bytecode.hpp:137
An owning sequence of exactly decoded instruction encodings.
Definition bytecode.hpp:304
std::vector< instruction > instructions
Instructions in increasing byte-offset order.
Definition bytecode.hpp:305
The invokedynamic instruction, including its reserved field.
Definition bytecode.hpp:211
constant_pool_index index
Index of a CONSTANT_InvokeDynamic entry.
Definition bytecode.hpp:213
std::uint16_t reserved
Format-reserved two-byte field; zero in valid class files.
Definition bytecode.hpp:214
The invokeinterface instruction, including its reserved byte.
Definition bytecode.hpp:201
std::uint8_t reserved
Format-reserved byte; zero in valid class files.
Definition bytecode.hpp:205
std::uint8_t count
Nonzero argument slot count, including the receiver.
Definition bytecode.hpp:204
constant_pool_index index
Index of a CONSTANT_InterfaceMethodref entry.
Definition bytecode.hpp:203
A one-byte local-variable-index instruction.
Definition bytecode.hpp:109
std::uint8_t index
Zero-based local-variable-array slot.
Definition bytecode.hpp:111
A JVM local-variable-array index.
Definition bytecode.hpp:30
std::uint16_t value
Zero-based local-variable-array slot.
Definition bytecode.hpp:31
One match/target pair in a lookupswitch instruction.
Definition bytecode.hpp:172
std::int32_t match
Lookup key; pairs must be strictly increasing in strict mode.
Definition bytecode.hpp:173
branch_displacement32 displacement
Branch target for this key, relative to the switch opcode.
Definition bytecode.hpp:174
An exact lookupswitch instruction, including alignment bytes.
Definition bytecode.hpp:191
std::vector< lookup_switch_pair > pairs
Strictly increasing match/target pairs.
Definition bytecode.hpp:195
std::vector< std::byte > padding
Exact zero-to-three bytes aligning the default operand to four bytes.
Definition bytecode.hpp:193
branch_displacement32 default_displacement
Target used when no pair matches.
Definition bytecode.hpp:194
The multianewarray instruction.
Definition bytecode.hpp:228
std::uint8_t dimensions
Nonzero number of leading array dimensions to allocate.
Definition bytecode.hpp:231
constant_pool_index index
Index of a CONSTANT_Class containing an array descriptor.
Definition bytecode.hpp:230
The newarray instruction.
Definition bytecode.hpp:220
newarray_type element_type
Primitive component kind selected by the atype operand.
Definition bytecode.hpp:222
An undecoded Code body retained by tooling mode.
Definition bytecode.hpp:311
std::vector< std::byte > bytes
Complete, byte-for-byte code array retained after decoding became unsafe.
Definition bytecode.hpp:312
A signed one-byte immediate instruction.
Definition bytecode.hpp:73
std::int8_t value
Immediate operand in host signed representation.
Definition bytecode.hpp:75
A signed two-byte immediate instruction.
Definition bytecode.hpp:82
std::int16_t value
Immediate operand in host signed representation.
Definition bytecode.hpp:84
An instruction whose encoding contains only its opcode.
Definition bytecode.hpp:65
An exact tableswitch instruction, including alignment bytes.
Definition bytecode.hpp:180
std::vector< std::byte > padding
Exact zero-to-three bytes aligning the default operand to four bytes.
Definition bytecode.hpp:182
std::int32_t low
Lowest table key; the highest key is derived from the target count.
Definition bytecode.hpp:184
std::vector< branch_displacement32 > displacements
Consecutive targets beginning at low; never empty in strict mode.
Definition bytecode.hpp:185
branch_displacement32 default_displacement
Target used when the key is outside the table.
Definition bytecode.hpp:183
The wide iinc form following the wide prefix.
Definition bytecode.hpp:153
local_variable_index index
Two-byte local int slot to update.
Definition bytecode.hpp:154
std::int16_t amount
Signed two-byte increment.
Definition bytecode.hpp:155
A complete wide-prefixed instruction.
Definition bytecode.hpp:164
wide_operand operand
Modified local instruction encoded after the wide prefix.
Definition bytecode.hpp:166
A wide local-variable instruction following the wide prefix.
Definition bytecode.hpp:145
local_variable_index index
Two-byte local-variable-array slot.
Definition bytecode.hpp:147
Fundamental class-file, constant-pool, and JAR value types.