@@ -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,28 @@ 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
521- // 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
509+ code.instructions .push_back (opcode);
510+
511+ // Placeholder for the immediate value, filled at the matching end instructions.
512+ push (code.instructions , uint32_t {0 }); // Diff to the end instruction.
524513
525- // 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+ // Fill in if's immediate with the offset of first instruction in else block.
515+ const auto target_pc = static_cast <uint32_t >(code.instructions .size ());
528516
529- // Set the imm values for else instruction.
530- auto * if_imm = code.immediates .data () + if_imm_offset;
517+ // Set the imm values for if instruction.
518+ auto * if_imm = code.instructions .data () + if_imm_offset;
531519 store (if_imm, target_pc);
532- if_imm += sizeof (target_pc);
533- store (if_imm, target_imm);
534- break ;
520+ continue ;
535521 }
536522
537523 case Instr::end:
@@ -549,26 +535,21 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, FuncIdx f
549535 const auto target_pc = control_stack.size () == 1 ?
550536 static_cast <uint32_t >(code.instructions .size ()) :
551537 static_cast <uint32_t >(code.instructions .size () + 1 );
552- const auto target_imm = static_cast <uint32_t >(code.immediates .size ());
553538
554539 if (frame.instruction == Instr::if_ || frame.instruction == Instr::else_)
555540 {
556541 // We're at the end instruction of the if block without else or at the end of
557- // else block. Fill in if/else's immediates with offsets of first instruction
542+ // else block. Fill in if/else's immediate with the offset of first instruction
558543 // after if/else block.
559- auto * if_imm = code.immediates .data () + frame.immediates_offset ;
544+ auto * if_imm = code.instructions .data () + frame.code_offset + 1 ;
560545 store (if_imm, target_pc);
561- if_imm += sizeof (target_pc);
562- store (if_imm, target_imm);
563546 }
564547
565548 // Fill in immediates all br/br_table instructions jumping out of this block.
566549 for (const auto br_imm_offset : frame.br_immediate_offsets )
567550 {
568- auto * br_imm = code.immediates .data () + br_imm_offset;
551+ auto * br_imm = code.instructions .data () + br_imm_offset;
569552 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));
572553 // stack drop and arity were already stored in br handler
573554 }
574555 }
@@ -596,13 +577,14 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, FuncIdx f
596577
597578 update_branch_stack (frame, branch_frame, operand_stack);
598579
599- push (code.immediates , get_branch_arity (branch_frame));
580+ code.instructions .push_back (opcode);
581+ push (code.instructions , get_branch_arity (branch_frame));
600582
601583 // Remember this br immediates offset to fill it at end instruction.
602- branch_frame.br_immediate_offsets .push_back (code.immediates .size ());
584+ branch_frame.br_immediate_offsets .push_back (code.instructions .size ());
603585
604586 push_branch_immediates (
605- branch_frame, static_cast <int >(operand_stack.size ()), code.immediates );
587+ branch_frame, static_cast <int >(operand_stack.size ()), code.instructions );
606588
607589 if (instr == Instr::br)
608590 mark_frame_unreachable (frame, operand_stack);
@@ -615,7 +597,7 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, FuncIdx f
615597 push_operand (operand_stack, *branch_frame.type );
616598 }
617599
618- break ;
600+ continue ;
619601 }
620602
621603 case Instr::br_table:
@@ -653,13 +635,13 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, FuncIdx f
653635 if (get_branch_frame_type (branch_frame) != default_branch_type)
654636 throw validation_error{" br_table labels have inconsistent types" };
655637
656- branch_frame.br_immediate_offsets .push_back (code.immediates .size ());
638+ branch_frame.br_immediate_offsets .push_back (code.instructions .size ());
657639 push_branch_immediates (
658- branch_frame, static_cast <int >(operand_stack.size ()), code.immediates );
640+ branch_frame, static_cast <int >(operand_stack.size ()), code.instructions );
659641 }
660- default_branch_frame.br_immediate_offsets .push_back (code.immediates .size ());
642+ default_branch_frame.br_immediate_offsets .push_back (code.instructions .size ());
661643 push_branch_immediates (
662- default_branch_frame, static_cast <int >(operand_stack.size ()), code.immediates );
644+ default_branch_frame, static_cast <int >(operand_stack.size ()), code.instructions );
663645
664646 mark_frame_unreachable (frame, operand_stack);
665647
@@ -676,15 +658,16 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, FuncIdx f
676658
677659 update_branch_stack (frame, branch_frame, operand_stack);
678660
679- push (code.immediates , get_branch_arity (branch_frame));
661+ code.instructions .push_back (opcode);
662+ push (code.instructions , get_branch_arity (branch_frame));
680663
681- branch_frame.br_immediate_offsets .push_back (code.immediates .size ());
664+ branch_frame.br_immediate_offsets .push_back (code.instructions .size ());
682665
683666 push_branch_immediates (
684- branch_frame, static_cast <int >(operand_stack.size ()), code.immediates );
667+ branch_frame, static_cast <int >(operand_stack.size ()), code.instructions );
685668
686669 mark_frame_unreachable (frame, operand_stack);
687- break ;
670+ continue ;
688671 }
689672
690673 case Instr::call:
0 commit comments