@@ -19,14 +19,6 @@ inline void store(uint8_t* dst, T value) noexcept
1919 __builtin_memcpy (dst, &value, sizeof (value));
2020}
2121
22- template <typename T>
23- inline void push (bytes& b, T value)
24- {
25- uint8_t storage[sizeof (T)];
26- store (storage, value);
27- b.append (storage, sizeof (storage));
28- }
29-
3022template <typename T>
3123inline void push (std::vector<uint8_t >& b, T value)
3224{
@@ -48,9 +40,6 @@ struct ControlFrame
4840 // / The target instruction code offset.
4941 const size_t code_offset{0 };
5042
51- // / The immediates offset for block instructions.
52- const size_t immediates_offset{0 };
53-
5443 // / The frame stack height of the parent frame.
5544 const int parent_stack_height{0 };
5645
@@ -62,11 +51,10 @@ struct ControlFrame
6251 std::vector<size_t > br_immediate_offsets{};
6352
6453 ControlFrame (Instr _instruction, std::optional<ValType> _type, int _parent_stack_height,
65- size_t _code_offset = 0 , size_t _immediates_offset = 0 ) noexcept
54+ size_t _code_offset = 0 ) noexcept
6655 : instruction{_instruction},
6756 type{_type},
6857 code_offset{_code_offset},
69- immediates_offset{_immediates_offset},
7058 parent_stack_height{_parent_stack_height}
7159 {}
7260};
@@ -210,16 +198,16 @@ inline void update_branch_stack(const ControlFrame& current_frame, const Control
210198 drop_operand (current_frame, operand_stack, from_valtype (*branch_frame_type));
211199}
212200
213- void push_branch_immediates (const ControlFrame& branch_frame, int stack_height, bytes& immediates)
201+ void push_branch_immediates (
202+ const ControlFrame& branch_frame, int stack_height, std::vector<uint8_t >& instructions)
214203{
215204 // How many stack items to drop when taking the branch.
216205 const auto stack_drop = stack_height - branch_frame.parent_stack_height ;
217206
218207 // Push frame start location as br immediates - these are final if frame is loop,
219208 // but for block/if/else these are just placeholders, to be filled at end instruction.
220- push (immediates, static_cast <uint32_t >(branch_frame.code_offset ));
221- push (immediates, static_cast <uint32_t >(branch_frame.immediates_offset ));
222- push (immediates, static_cast <uint32_t >(stack_drop));
209+ push (instructions, static_cast <uint32_t >(branch_frame.code_offset ));
210+ push (instructions, static_cast <uint32_t >(stack_drop));
223211}
224212
225213inline void mark_frame_unreachable (
@@ -473,7 +461,7 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, FuncIdx f
473461
474462 // Push label with immediates offset after arity.
475463 control_stack.emplace (Instr::block, block_type, static_cast <int >(operand_stack.size ()),
476- code.instructions .size (), code. immediates . size () );
464+ code.instructions .size ());
477465 break ;
478466 }
479467
@@ -483,7 +471,7 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, FuncIdx f
483471 std::tie (loop_type, pos) = parse_blocktype (pos, end);
484472
485473 control_stack.emplace (Instr::loop, loop_type, static_cast <int >(operand_stack.size ()),
486- code.instructions .size (), code. immediates . size () );
474+ code.instructions .size ());
487475 break ;
488476 }
489477
@@ -493,12 +481,12 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, FuncIdx f
493481 std::tie (if_type, pos) = parse_blocktype (pos, end);
494482
495483 control_stack.emplace (Instr::if_, if_type, static_cast <int >(operand_stack.size ()),
496- code.instructions .size (), code. immediates . size () );
484+ code.instructions .size ());
497485
498486 // Placeholders for immediate values, filled at the matching end or else instructions.
499- push ( code.immediates , uint32_t { 0 }); // Diff to the else instruction
500- push (code.immediates , uint32_t {0 }); // Diff for the immediates.
501- break ;
487+ code.instructions . push_back (opcode);
488+ push (code.instructions , uint32_t {0 }); // Diff to the else instruction
489+ continue ;
502490 }
503491
504492 case Instr::else_:
@@ -508,30 +496,27 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, FuncIdx f
508496
509497 update_result_stack (frame, operand_stack); // else is the end of if.
510498
511- const auto if_imm_offset = frame.immediates_offset ;
499+ const auto if_imm_offset = frame.code_offset + 1 ;
512500 const auto frame_type = frame.type ;
513501 auto frame_br_immediate_offsets = std::move (frame.br_immediate_offsets );
514502
515503 control_stack.pop ();
516504 control_stack.emplace (Instr::else_, frame_type, static_cast <int >(operand_stack.size ()),
517- code.instructions .size (), code. immediates . size () );
505+ code.instructions .size ());
518506 // br immediates from `then` branch will need to be filled at the end of `else`
519507 control_stack.top ().br_immediate_offsets = std::move (frame_br_immediate_offsets);
520508
521509 // Placeholders for immediate values, filled at the matching end instructions.
522- push ( code.immediates , uint32_t { 0 }); // Diff to the end instruction.
523- push (code.immediates , uint32_t {0 }); // Diff for the immediates
510+ code.instructions . push_back (opcode);
511+ push (code.instructions , uint32_t {0 }); // Diff to the end instruction.
524512
525513 // Fill in if's immediates with offsets of first instruction in else block.
526- const auto target_pc = static_cast <uint32_t >(code.instructions .size () + 1 );
527- const auto target_imm = static_cast <uint32_t >(code.immediates .size ());
514+ const auto target_pc = static_cast <uint32_t >(code.instructions .size ());
528515
529- // Set the imm values for else instruction.
530- auto * if_imm = code.immediates .data () + if_imm_offset;
516+ // Set the imm values for if instruction.
517+ auto * if_imm = code.instructions .data () + if_imm_offset;
531518 store (if_imm, target_pc);
532- if_imm += sizeof (target_pc);
533- store (if_imm, target_imm);
534- break ;
519+ continue ;
535520 }
536521
537522 case Instr::end:
@@ -549,26 +534,21 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, FuncIdx f
549534 const auto target_pc = control_stack.size () == 1 ?
550535 static_cast <uint32_t >(code.instructions .size ()) :
551536 static_cast <uint32_t >(code.instructions .size () + 1 );
552- const auto target_imm = static_cast <uint32_t >(code.immediates .size ());
553537
554538 if (frame.instruction == Instr::if_ || frame.instruction == Instr::else_)
555539 {
556540 // We're at the end instruction of the if block without else or at the end of
557541 // else block. Fill in if/else's immediates with offsets of first instruction
558542 // after if/else block.
559- auto * if_imm = code.immediates .data () + frame.immediates_offset ;
543+ auto * if_imm = code.instructions .data () + frame.code_offset + 1 ;
560544 store (if_imm, target_pc);
561- if_imm += sizeof (target_pc);
562- store (if_imm, target_imm);
563545 }
564546
565547 // Fill in immediates all br/br_table instructions jumping out of this block.
566548 for (const auto br_imm_offset : frame.br_immediate_offsets )
567549 {
568- auto * br_imm = code.immediates .data () + br_imm_offset;
550+ auto * br_imm = code.instructions .data () + br_imm_offset;
569551 store (br_imm, static_cast <uint32_t >(target_pc));
570- br_imm += sizeof (uint32_t );
571- store (br_imm, static_cast <uint32_t >(target_imm));
572552 // stack drop and arity were already stored in br handler
573553 }
574554 }
@@ -596,13 +576,14 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, FuncIdx f
596576
597577 update_branch_stack (frame, branch_frame, operand_stack);
598578
599- push (code.immediates , get_branch_arity (branch_frame));
579+ code.instructions .push_back (opcode);
580+ push (code.instructions , get_branch_arity (branch_frame));
600581
601582 // Remember this br immediates offset to fill it at end instruction.
602- branch_frame.br_immediate_offsets .push_back (code.immediates .size ());
583+ branch_frame.br_immediate_offsets .push_back (code.instructions .size ());
603584
604585 push_branch_immediates (
605- branch_frame, static_cast <int >(operand_stack.size ()), code.immediates );
586+ branch_frame, static_cast <int >(operand_stack.size ()), code.instructions );
606587
607588 if (instr == Instr::br)
608589 mark_frame_unreachable (frame, operand_stack);
@@ -615,7 +596,7 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, FuncIdx f
615596 push_operand (operand_stack, *branch_frame.type );
616597 }
617598
618- break ;
599+ continue ;
619600 }
620601
621602 case Instr::br_table:
@@ -653,13 +634,13 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, FuncIdx f
653634 if (get_branch_frame_type (branch_frame) != default_branch_type)
654635 throw validation_error{" br_table labels have inconsistent types" };
655636
656- branch_frame.br_immediate_offsets .push_back (code.immediates .size ());
637+ branch_frame.br_immediate_offsets .push_back (code.instructions .size ());
657638 push_branch_immediates (
658- branch_frame, static_cast <int >(operand_stack.size ()), code.immediates );
639+ branch_frame, static_cast <int >(operand_stack.size ()), code.instructions );
659640 }
660- default_branch_frame.br_immediate_offsets .push_back (code.immediates .size ());
641+ default_branch_frame.br_immediate_offsets .push_back (code.instructions .size ());
661642 push_branch_immediates (
662- default_branch_frame, static_cast <int >(operand_stack.size ()), code.immediates );
643+ default_branch_frame, static_cast <int >(operand_stack.size ()), code.instructions );
663644
664645 mark_frame_unreachable (frame, operand_stack);
665646
@@ -676,15 +657,16 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, FuncIdx f
676657
677658 update_branch_stack (frame, branch_frame, operand_stack);
678659
679- push (code.immediates , get_branch_arity (branch_frame));
660+ code.instructions .push_back (opcode);
661+ push (code.instructions , get_branch_arity (branch_frame));
680662
681- branch_frame.br_immediate_offsets .push_back (code.immediates .size ());
663+ branch_frame.br_immediate_offsets .push_back (code.instructions .size ());
682664
683665 push_branch_immediates (
684- branch_frame, static_cast <int >(operand_stack.size ()), code.immediates );
666+ branch_frame, static_cast <int >(operand_stack.size ()), code.instructions );
685667
686668 mark_frame_unreachable (frame, operand_stack);
687- break ;
669+ continue ;
688670 }
689671
690672 case Instr::call:
0 commit comments