Skip to main content

thalir_core/builder/
block_builder.rs

1use super::{
2    inst_builder::{InstBuilder, InstBuilderBase, InstBuilderExt},
3    IRContext, IRRegistry,
4};
5use crate::{
6    block::{BasicBlock, BlockId, Terminator},
7    contract::EventId,
8    instructions::{CallTarget, ContextVariable, Instruction, StorageKey},
9    types::Type,
10    values::{Constant, SourceLocation, Value},
11    Result,
12};
13use num_bigint::{BigInt, BigUint};
14use std::collections::HashMap;
15
16pub struct BlockBuilder<'a> {
17    pub block_id: BlockId,
18    function_name: String,
19    instructions: Vec<Instruction>,
20    context: &'a mut IRContext,
21    registry: &'a mut IRRegistry,
22    is_sealed: bool,
23    current_source_location: Option<SourceLocation>,
24    instruction_locations: HashMap<usize, SourceLocation>,
25}
26
27impl<'a> BlockBuilder<'a> {
28    pub fn new(
29        block_id: BlockId,
30        function_name: String,
31        context: &'a mut IRContext,
32        registry: &'a mut IRRegistry,
33    ) -> Self {
34        Self {
35            block_id,
36            function_name,
37            instructions: Vec::new(),
38            context,
39            registry,
40            is_sealed: false,
41            current_source_location: None,
42            instruction_locations: HashMap::new(),
43        }
44    }
45
46    pub fn set_source_location(&mut self, location: SourceLocation) {
47        self.current_source_location = Some(location);
48    }
49
50    pub fn clear_source_location(&mut self) {
51        self.current_source_location = None;
52    }
53
54    fn record_instruction_location(&mut self) {
55        if let Some(ref location) = self.current_source_location {
56            let index = self.instructions.len();
57            self.instruction_locations.insert(index, location.clone());
58        }
59    }
60
61    fn push_instruction(&mut self, inst: Instruction) {
62        self.record_instruction_location();
63        self.instructions.push(inst);
64    }
65
66    pub fn block_id(&self) -> BlockId {
67        self.block_id
68    }
69
70    pub fn add(&mut self, left: Value, right: Value, ty: Type) -> Value {
71        let result = self.new_temp();
72        self.push_instruction(Instruction::Add {
73            result: result.clone(),
74            left,
75            right,
76            ty,
77        });
78        result
79    }
80
81    pub fn sub(&mut self, left: Value, right: Value, ty: Type) -> Value {
82        let result = self.new_temp();
83        self.push_instruction(Instruction::Sub {
84            result: result.clone(),
85            left,
86            right,
87            ty,
88        });
89        result
90    }
91
92    pub fn mul(&mut self, left: Value, right: Value, ty: Type) -> Value {
93        let result = self.new_temp();
94        self.push_instruction(Instruction::Mul {
95            result: result.clone(),
96            left,
97            right,
98            ty,
99        });
100        result
101    }
102
103    pub fn div(&mut self, left: Value, right: Value, ty: Type) -> Value {
104        let result = self.new_temp();
105        self.push_instruction(Instruction::Div {
106            result: result.clone(),
107            left,
108            right,
109            ty,
110        });
111        result
112    }
113
114    pub fn mod_(&mut self, left: Value, right: Value, ty: Type) -> Value {
115        let result = self.new_temp();
116        self.push_instruction(Instruction::Mod {
117            result: result.clone(),
118            left,
119            right,
120            ty,
121        });
122        result
123    }
124
125    pub fn pow(&mut self, base: Value, exp: Value) -> Value {
126        let result = self.new_temp();
127        self.push_instruction(Instruction::Pow {
128            result: result.clone(),
129            base,
130            exp,
131        });
132        result
133    }
134
135    pub fn checked_add(&mut self, left: Value, right: Value, ty: Type) -> Value {
136        let result = self.new_temp();
137        self.push_instruction(Instruction::CheckedAdd {
138            result: result.clone(),
139            left,
140            right,
141            ty,
142        });
143        result
144    }
145
146    pub fn checked_sub(&mut self, left: Value, right: Value, ty: Type) -> Value {
147        let result = self.new_temp();
148        self.push_instruction(Instruction::CheckedSub {
149            result: result.clone(),
150            left,
151            right,
152            ty,
153        });
154        result
155    }
156
157    pub fn checked_mul(&mut self, left: Value, right: Value, ty: Type) -> Value {
158        let result = self.new_temp();
159        self.push_instruction(Instruction::CheckedMul {
160            result: result.clone(),
161            left,
162            right,
163            ty,
164        });
165        result
166    }
167
168    pub fn and(&mut self, left: Value, right: Value) -> Value {
169        let result = self.new_temp();
170        self.push_instruction(Instruction::And {
171            result: result.clone(),
172            left,
173            right,
174        });
175        result
176    }
177
178    pub fn or(&mut self, left: Value, right: Value) -> Value {
179        let result = self.new_temp();
180        self.push_instruction(Instruction::Or {
181            result: result.clone(),
182            left,
183            right,
184        });
185        result
186    }
187
188    pub fn xor(&mut self, left: Value, right: Value) -> Value {
189        let result = self.new_temp();
190        self.push_instruction(Instruction::Xor {
191            result: result.clone(),
192            left,
193            right,
194        });
195        result
196    }
197
198    pub fn not(&mut self, operand: Value) -> Value {
199        let result = self.new_temp();
200        self.push_instruction(Instruction::Not {
201            result: result.clone(),
202            operand,
203        });
204        result
205    }
206
207    pub fn shl(&mut self, value: Value, shift: Value) -> Value {
208        let result = self.new_temp();
209        self.push_instruction(Instruction::Shl {
210            result: result.clone(),
211            value,
212            shift,
213        });
214        result
215    }
216
217    pub fn shr(&mut self, value: Value, shift: Value) -> Value {
218        let result = self.new_temp();
219        self.push_instruction(Instruction::Shr {
220            result: result.clone(),
221            value,
222            shift,
223        });
224        result
225    }
226
227    pub fn sar(&mut self, value: Value, shift: Value) -> Value {
228        let result = self.new_temp();
229        self.push_instruction(Instruction::Sar {
230            result: result.clone(),
231            value,
232            shift,
233        });
234        result
235    }
236
237    pub fn eq(&mut self, left: Value, right: Value) -> Value {
238        let result = self.new_temp();
239        self.push_instruction(Instruction::Eq {
240            result: result.clone(),
241            left,
242            right,
243        });
244        result
245    }
246
247    pub fn ne(&mut self, left: Value, right: Value) -> Value {
248        let result = self.new_temp();
249        self.push_instruction(Instruction::Ne {
250            result: result.clone(),
251            left,
252            right,
253        });
254        result
255    }
256
257    pub fn lt(&mut self, left: Value, right: Value) -> Value {
258        let result = self.new_temp();
259        self.push_instruction(Instruction::Lt {
260            result: result.clone(),
261            left,
262            right,
263        });
264        result
265    }
266
267    pub fn gt(&mut self, left: Value, right: Value) -> Value {
268        let result = self.new_temp();
269        self.push_instruction(Instruction::Gt {
270            result: result.clone(),
271            left,
272            right,
273        });
274        result
275    }
276
277    pub fn le(&mut self, left: Value, right: Value) -> Value {
278        let result = self.new_temp();
279        self.push_instruction(Instruction::Le {
280            result: result.clone(),
281            left,
282            right,
283        });
284        result
285    }
286
287    pub fn ge(&mut self, left: Value, right: Value) -> Value {
288        let result = self.new_temp();
289        self.push_instruction(Instruction::Ge {
290            result: result.clone(),
291            left,
292            right,
293        });
294        result
295    }
296
297    pub fn select(&mut self, condition: Value, then_val: Value, else_val: Value) -> Value {
298        let result = self.new_temp();
299        self.push_instruction(Instruction::Select {
300            result: result.clone(),
301            condition,
302            then_val,
303            else_val,
304        });
305        result
306    }
307
308    pub fn allocate(&mut self, ty: Type, size: crate::instructions::Size) -> Value {
309        let result = self.new_temp();
310        self.push_instruction(Instruction::Allocate {
311            result: result.clone(),
312            ty,
313            size,
314        });
315        result
316    }
317
318    pub fn storage_load(&mut self, slot: BigUint) -> Value {
319        let result = self.new_temp();
320        let key = StorageKey::Slot(slot);
321        self.push_instruction(Instruction::StorageLoad {
322            result: result.clone(),
323            key,
324        });
325        result
326    }
327
328    pub fn storage_store(&mut self, slot: BigUint, value: Value) {
329        let key = StorageKey::Slot(slot);
330        self.push_instruction(Instruction::StorageStore { key, value });
331    }
332
333    pub fn mapping_load(&mut self, mapping: Value, key: Value) -> Value {
334        let result = self.new_temp();
335        self.push_instruction(Instruction::MappingLoad {
336            result: result.clone(),
337            mapping,
338            key,
339        });
340        result
341    }
342
343    pub fn mapping_store(&mut self, mapping: Value, key: Value, value: Value) {
344        self.push_instruction(Instruction::MappingStore {
345            mapping,
346            key,
347            value,
348        });
349    }
350
351    pub fn array_load(&mut self, array: Value, index: Value) -> Value {
352        let result = self.new_temp();
353        self.push_instruction(Instruction::ArrayLoad {
354            result: result.clone(),
355            array,
356            index,
357        });
358        result
359    }
360
361    pub fn array_store(&mut self, array: Value, index: Value, value: Value) {
362        self.push_instruction(Instruction::ArrayStore {
363            array,
364            index,
365            value,
366        });
367    }
368
369    pub fn array_length(&mut self, array: Value) -> Value {
370        let result = self.new_temp();
371        self.push_instruction(Instruction::ArrayLength {
372            result: result.clone(),
373            array,
374        });
375        result
376    }
377
378    pub fn array_push(&mut self, array: Value, value: Value) {
379        self.push_instruction(Instruction::ArrayPush { array, value });
380    }
381
382    pub fn array_pop(&mut self, array: Value) -> Value {
383        let result = self.new_temp();
384        self.push_instruction(Instruction::ArrayPop {
385            result: result.clone(),
386            array,
387        });
388        result
389    }
390
391    pub fn msg_sender(&mut self) -> Value {
392        let result = self.new_temp();
393        self.push_instruction(Instruction::GetContext {
394            result: result.clone(),
395            var: ContextVariable::MsgSender,
396        });
397        result
398    }
399
400    pub fn msg_value(&mut self) -> Value {
401        let result = self.new_temp();
402        self.push_instruction(Instruction::GetContext {
403            result: result.clone(),
404            var: ContextVariable::MsgValue,
405        });
406        result
407    }
408
409    pub fn block_number(&mut self) -> Value {
410        let result = self.new_temp();
411        self.push_instruction(Instruction::GetContext {
412            result: result.clone(),
413            var: ContextVariable::BlockNumber,
414        });
415        result
416    }
417
418    pub fn block_timestamp(&mut self) -> Value {
419        let result = self.new_temp();
420        self.push_instruction(Instruction::GetContext {
421            result: result.clone(),
422            var: ContextVariable::BlockTimestamp,
423        });
424        result
425    }
426
427    pub fn call_internal(&mut self, name: &str, args: Vec<Value>) -> Value {
428        let result = self.new_temp();
429        self.push_instruction(Instruction::Call {
430            result: result.clone(),
431            target: CallTarget::Internal(name.to_string()),
432            args,
433            value: None,
434        });
435        result
436    }
437
438    pub fn call_external(
439        &mut self,
440        target: Value,
441        selector: Value,
442        args: Vec<Value>,
443        value: Option<Value>,
444    ) -> Value {
445        let result = self.new_temp();
446
447        let mut call_args = vec![selector];
448        call_args.extend(args);
449        self.push_instruction(Instruction::Call {
450            result: result.clone(),
451            target: CallTarget::External(target),
452            args: call_args,
453            value,
454        });
455        result
456    }
457
458    pub fn keccak256(&mut self, data: Value, len: Value) -> Value {
459        let result = self.new_temp();
460        self.push_instruction(Instruction::Keccak256 {
461            result: result.clone(),
462            data,
463            len,
464        });
465        result
466    }
467
468    pub fn sha256(&mut self, data: Value, len: Value) -> Value {
469        let result = self.new_temp();
470        self.push_instruction(Instruction::Sha256 {
471            result: result.clone(),
472            data,
473            len,
474        });
475        result
476    }
477
478    pub fn emit_event(&mut self, event_id: EventId, topics: Vec<Value>, data: Vec<Value>) {
479        self.push_instruction(Instruction::EmitEvent {
480            event: event_id,
481            topics,
482            data,
483        });
484    }
485
486    pub fn cast(&mut self, value: Value, to: Type) -> Value {
487        let result = self.new_temp();
488        self.push_instruction(Instruction::Cast {
489            result: result.clone(),
490            value,
491            to,
492        });
493        result
494    }
495
496    pub fn assert(&mut self, condition: Value, message: &str) {
497        self.push_instruction(Instruction::Assert {
498            condition,
499            message: message.to_string(),
500        });
501    }
502
503    pub fn require(&mut self, condition: Value, message: &str) {
504        self.push_instruction(Instruction::Require {
505            condition,
506            message: message.to_string(),
507        });
508    }
509
510    pub fn assign(&mut self, result: Value, value: Value) {
511        self.push_instruction(Instruction::Assign { result, value });
512    }
513
514    pub fn phi(&mut self, values: Vec<(BlockId, Value)>) -> Value {
515        let result = self.new_temp();
516        self.push_instruction(Instruction::Phi {
517            result: result.clone(),
518            values,
519        });
520        result
521    }
522
523    pub fn jump(&mut self, target: BlockId) -> Result<()> {
524        self.seal_with_terminator(Terminator::Jump(target, Vec::new()))
525    }
526
527    pub fn branch(
528        &mut self,
529        condition: Value,
530        then_block: BlockId,
531        else_block: BlockId,
532    ) -> Result<()> {
533        self.seal_with_terminator(Terminator::Branch {
534            condition,
535            then_block,
536            else_block,
537            then_args: Vec::new(),
538            else_args: Vec::new(),
539        })
540    }
541
542    pub fn return_value(&mut self, value: Value) -> Result<()> {
543        self.seal_with_terminator(Terminator::Return(Some(value)))
544    }
545
546    pub fn return_void(&mut self) -> Result<()> {
547        self.seal_with_terminator(Terminator::Return(None))
548    }
549
550    pub fn revert(&mut self, message: &str) -> Result<()> {
551        self.seal_with_terminator(Terminator::Revert(message.to_string()))
552    }
553
554    pub fn is_sealed(&self) -> bool {
555        self.is_sealed
556    }
557
558    pub fn seal_with_terminator(&mut self, terminator: Terminator) -> Result<()> {
559        if self.is_sealed {
560            return Err(crate::IrError::BuilderError(format!(
561                "Block {} already sealed",
562                self.block_id
563            )));
564        }
565
566        let mut block = BasicBlock::new(self.block_id);
567        block.instructions = self.instructions.clone();
568        block.terminator = terminator;
569
570        block.metadata.instruction_locations = self.instruction_locations.clone();
571
572        self.registry.add_block(self.function_name.clone(), block)?;
573        self.is_sealed = true;
574        Ok(())
575    }
576
577    pub fn new_temp(&mut self) -> Value {
578        let temp_id = self.context.ssa().new_temp();
579        Value::Temp(temp_id)
580    }
581
582    pub fn constant_uint(&self, value: u64, bits: u16) -> Value {
583        Value::Constant(Constant::Uint(BigUint::from(value), bits))
584    }
585
586    pub fn constant_int(&self, value: i64, bits: u16) -> Value {
587        Value::Constant(Constant::Int(BigInt::from(value), bits))
588    }
589
590    pub fn constant_bool(&self, value: bool) -> Value {
591        Value::Constant(Constant::Bool(value))
592    }
593
594    pub fn constant_address(&self, bytes: [u8; 20]) -> Value {
595        Value::Constant(Constant::Address(bytes))
596    }
597}
598
599impl<'a> InstBuilderBase<'a> for BlockBuilder<'a> {
600    fn new_temp(&mut self) -> Value {
601        let temp_id = self.context.ssa().new_temp();
602        Value::Temp(temp_id)
603    }
604
605    fn current_block(&self) -> BlockId {
606        self.block_id
607    }
608
609    fn switch_to_block(&mut self, block: BlockId) {
610        self.block_id = block;
611        self.context.set_current_block(block);
612    }
613}
614
615impl<'a> InstBuilderExt<'a> for BlockBuilder<'a> {
616    fn storage_load(&mut self, slot: BigUint) -> Value {
617        let result = self.new_temp();
618        let key = StorageKey::Slot(slot);
619        self.push_instruction(Instruction::StorageLoad {
620            result: result.clone(),
621            key,
622        });
623        result
624    }
625
626    fn storage_store(&mut self, slot: BigUint, value: Value) {
627        let key = StorageKey::Slot(slot);
628        self.push_instruction(Instruction::StorageStore { key, value });
629    }
630
631    fn storage_load_dynamic(&mut self, slot: Value) -> Value {
632        let result = self.new_temp();
633        let key = StorageKey::Dynamic(slot);
634        self.push_instruction(Instruction::StorageLoad {
635            result: result.clone(),
636            key,
637        });
638        result
639    }
640
641    fn storage_store_dynamic(&mut self, slot: Value, value: Value) {
642        let key = StorageKey::Dynamic(slot);
643        self.push_instruction(Instruction::StorageStore { key, value });
644    }
645
646    fn mapping_load(&mut self, mapping: Value, key: Value) -> Value {
647        let result = self.new_temp();
648        self.push_instruction(Instruction::MappingLoad {
649            result: result.clone(),
650            mapping,
651            key,
652        });
653        result
654    }
655
656    fn mapping_store(&mut self, mapping: Value, key: Value, value: Value) {
657        self.push_instruction(Instruction::MappingStore {
658            mapping,
659            key,
660            value,
661        });
662    }
663
664    fn array_load(&mut self, array: Value, index: Value) -> Value {
665        let result = self.new_temp();
666        self.push_instruction(Instruction::ArrayLoad {
667            result: result.clone(),
668            array,
669            index,
670        });
671        result
672    }
673
674    fn array_store(&mut self, array: Value, index: Value, value: Value) {
675        self.push_instruction(Instruction::ArrayStore {
676            array,
677            index,
678            value,
679        });
680    }
681
682    fn array_length(&mut self, array: Value) -> Value {
683        let result = self.new_temp();
684        self.push_instruction(Instruction::ArrayLength {
685            result: result.clone(),
686            array,
687        });
688        result
689    }
690
691    fn array_push(&mut self, array: Value, value: Value) {
692        self.push_instruction(Instruction::ArrayPush { array, value });
693    }
694
695    fn array_pop(&mut self, array: Value) -> Value {
696        let result = self.new_temp();
697        self.push_instruction(Instruction::ArrayPop {
698            result: result.clone(),
699            array,
700        });
701        result
702    }
703
704    fn msg_sender(&mut self) -> Value {
705        let result = self.new_temp();
706        self.push_instruction(Instruction::GetContext {
707            result: result.clone(),
708            var: ContextVariable::MsgSender,
709        });
710        result
711    }
712
713    fn msg_value(&mut self) -> Value {
714        let result = self.new_temp();
715        self.push_instruction(Instruction::GetContext {
716            result: result.clone(),
717            var: ContextVariable::MsgValue,
718        });
719        result
720    }
721
722    fn msg_data(&mut self) -> Value {
723        let result = self.new_temp();
724        self.push_instruction(Instruction::GetContext {
725            result: result.clone(),
726            var: ContextVariable::MsgData,
727        });
728        result
729    }
730
731    fn block_number(&mut self) -> Value {
732        let result = self.new_temp();
733        self.push_instruction(Instruction::GetContext {
734            result: result.clone(),
735            var: ContextVariable::BlockNumber,
736        });
737        result
738    }
739
740    fn block_timestamp(&mut self) -> Value {
741        let result = self.new_temp();
742        self.push_instruction(Instruction::GetContext {
743            result: result.clone(),
744            var: ContextVariable::BlockTimestamp,
745        });
746        result
747    }
748
749    fn block_difficulty(&mut self) -> Value {
750        let result = self.new_temp();
751        self.push_instruction(Instruction::GetContext {
752            result: result.clone(),
753            var: ContextVariable::BlockDifficulty,
754        });
755        result
756    }
757
758    fn block_gaslimit(&mut self) -> Value {
759        let result = self.new_temp();
760        self.push_instruction(Instruction::GetContext {
761            result: result.clone(),
762            var: ContextVariable::BlockGasLimit,
763        });
764        result
765    }
766
767    fn block_coinbase(&mut self) -> Value {
768        let result = self.new_temp();
769        self.push_instruction(Instruction::GetContext {
770            result: result.clone(),
771            var: ContextVariable::BlockCoinbase,
772        });
773        result
774    }
775
776    fn tx_origin(&mut self) -> Value {
777        let result = self.new_temp();
778        self.push_instruction(Instruction::GetContext {
779            result: result.clone(),
780            var: ContextVariable::TxOrigin,
781        });
782        result
783    }
784
785    fn tx_gasprice(&mut self) -> Value {
786        let result = self.new_temp();
787        self.push_instruction(Instruction::GetContext {
788            result: result.clone(),
789            var: ContextVariable::TxGasPrice,
790        });
791        result
792    }
793
794    fn gas_left(&mut self) -> Value {
795        let result = self.new_temp();
796        self.push_instruction(Instruction::GetContext {
797            result: result.clone(),
798            var: ContextVariable::GasLeft,
799        });
800        result
801    }
802
803    fn msg_sig(&mut self) -> Value {
804        let result = self.new_temp();
805        self.push_instruction(Instruction::GetContext {
806            result: result.clone(),
807            var: ContextVariable::MsgSig,
808        });
809        result
810    }
811
812    fn block_chainid(&mut self) -> Value {
813        let result = self.new_temp();
814        self.push_instruction(Instruction::GetContext {
815            result: result.clone(),
816            var: ContextVariable::ChainId,
817        });
818        result
819    }
820
821    fn block_basefee(&mut self) -> Value {
822        let result = self.new_temp();
823        self.push_instruction(Instruction::GetContext {
824            result: result.clone(),
825            var: ContextVariable::BlockBaseFee,
826        });
827        result
828    }
829
830    fn call_internal(&mut self, name: &str, args: Vec<Value>) -> Value {
831        let result = self.new_temp();
832        self.push_instruction(Instruction::Call {
833            result: result.clone(),
834            target: CallTarget::Internal(name.to_string()),
835            args,
836            value: None,
837        });
838        result
839    }
840
841    fn call_external(
842        &mut self,
843        target: Value,
844        selector: Value,
845        args: Vec<Value>,
846        value: Option<Value>,
847    ) -> Value {
848        self.call_external(target, selector, args, value)
849    }
850
851    fn delegate_call(&mut self, target: Value, selector: Value, args: Vec<Value>) -> Value {
852        let result = self.new_temp();
853        self.push_instruction(Instruction::DelegateCall {
854            result: result.clone(),
855            target,
856            selector,
857            args,
858        });
859        result
860    }
861
862    fn static_call(&mut self, target: Value, selector: Value, args: Vec<Value>) -> Value {
863        let result = self.new_temp();
864        self.push_instruction(Instruction::StaticCall {
865            result: result.clone(),
866            target,
867            selector,
868            args,
869        });
870        result
871    }
872
873    fn emit_event(&mut self, event: EventId, topics: Vec<Value>, data: Vec<Value>) {
874        self.push_instruction(Instruction::EmitEvent {
875            event,
876            topics,
877            data,
878        });
879    }
880
881    fn keccak256(&mut self, data: Value, len: Value) -> Value {
882        let result = self.new_temp();
883        self.push_instruction(Instruction::Keccak256 {
884            result: result.clone(),
885            data,
886            len,
887        });
888        result
889    }
890
891    fn sha256(&mut self, data: Value, len: Value) -> Value {
892        let result = self.new_temp();
893        self.push_instruction(Instruction::Sha256 {
894            result: result.clone(),
895            data,
896            len,
897        });
898        result
899    }
900
901    fn ripemd160(&mut self, data: Value, len: Value) -> Value {
902        let result = self.new_temp();
903        self.push_instruction(Instruction::Ripemd160 {
904            result: result.clone(),
905            data,
906            len,
907        });
908        result
909    }
910
911    fn ecrecover(&mut self, hash: Value, v: Value, r: Value, s: Value) -> Value {
912        let result = self.new_temp();
913        self.push_instruction(Instruction::EcRecover {
914            result: result.clone(),
915            hash,
916            v,
917            r,
918            s,
919        });
920        result
921    }
922
923    fn checked_add(&mut self, left: Value, right: Value, ty: Type) -> Value {
924        let result = self.new_temp();
925        self.push_instruction(Instruction::CheckedAdd {
926            result: result.clone(),
927            left,
928            right,
929            ty,
930        });
931        result
932    }
933
934    fn checked_sub(&mut self, left: Value, right: Value, ty: Type) -> Value {
935        let result = self.new_temp();
936        self.push_instruction(Instruction::CheckedSub {
937            result: result.clone(),
938            left,
939            right,
940            ty,
941        });
942        result
943    }
944
945    fn checked_mul(&mut self, left: Value, right: Value, ty: Type) -> Value {
946        let result = self.new_temp();
947        self.push_instruction(Instruction::CheckedMul {
948            result: result.clone(),
949            left,
950            right,
951            ty,
952        });
953        result
954    }
955
956    fn checked_div(&mut self, left: Value, right: Value, ty: Type) -> Value {
957        let result = self.new_temp();
958        self.push_instruction(Instruction::CheckedDiv {
959            result: result.clone(),
960            left,
961            right,
962            ty,
963        });
964        result
965    }
966
967    fn require(&mut self, condition: Value, message: &str) {
968        self.push_instruction(Instruction::Require {
969            condition,
970            message: message.to_string(),
971        });
972    }
973
974    fn assert(&mut self, condition: Value, message: &str) {
975        self.push_instruction(Instruction::Assert {
976            condition,
977            message: message.to_string(),
978        });
979    }
980
981    fn revert(&mut self, message: &str) {
982        self.push_instruction(Instruction::Revert {
983            message: message.to_string(),
984        });
985    }
986
987    fn memory_alloc(&mut self, size: Value) -> Value {
988        let result = self.new_temp();
989        self.push_instruction(Instruction::MemoryAlloc {
990            result: result.clone(),
991            size,
992        });
993        result
994    }
995
996    fn memory_copy(&mut self, dest: Value, src: Value, size: Value) {
997        self.push_instruction(Instruction::MemoryCopy { dest, src, size });
998    }
999
1000    fn memory_size(&mut self) -> Value {
1001        let result = self.new_temp();
1002        self.push_instruction(Instruction::MemorySize {
1003            result: result.clone(),
1004        });
1005        result
1006    }
1007
1008    fn cast(&mut self, value: Value, to: Type) -> Value {
1009        let result = self.new_temp();
1010        self.push_instruction(Instruction::Cast {
1011            result: result.clone(),
1012            value,
1013            to,
1014        });
1015        result
1016    }
1017
1018    fn zext(&mut self, value: Value, to: Type) -> Value {
1019        let result = self.new_temp();
1020        self.push_instruction(Instruction::ZeroExtend {
1021            result: result.clone(),
1022            value,
1023            to,
1024        });
1025        result
1026    }
1027
1028    fn sext(&mut self, value: Value, to: Type) -> Value {
1029        let result = self.new_temp();
1030        self.push_instruction(Instruction::SignExtend {
1031            result: result.clone(),
1032            value,
1033            to,
1034        });
1035        result
1036    }
1037
1038    fn trunc(&mut self, value: Value, to: Type) -> Value {
1039        let result = self.new_temp();
1040        self.push_instruction(Instruction::Truncate {
1041            result: result.clone(),
1042            value,
1043            to,
1044        });
1045        result
1046    }
1047}
1048
1049impl<'a> InstBuilder<'a> for BlockBuilder<'a> {
1050    fn add(&mut self, left: Value, right: Value, ty: Type) -> Value {
1051        let result = self.new_temp();
1052        self.push_instruction(Instruction::Add {
1053            result: result.clone(),
1054            left,
1055            right,
1056            ty,
1057        });
1058        result
1059    }
1060
1061    fn sub(&mut self, left: Value, right: Value, ty: Type) -> Value {
1062        let result = self.new_temp();
1063        self.push_instruction(Instruction::Sub {
1064            result: result.clone(),
1065            left,
1066            right,
1067            ty,
1068        });
1069        result
1070    }
1071
1072    fn mul(&mut self, left: Value, right: Value, ty: Type) -> Value {
1073        let result = self.new_temp();
1074        self.push_instruction(Instruction::Mul {
1075            result: result.clone(),
1076            left,
1077            right,
1078            ty,
1079        });
1080        result
1081    }
1082
1083    fn div(&mut self, left: Value, right: Value, ty: Type) -> Value {
1084        let result = self.new_temp();
1085        self.push_instruction(Instruction::Div {
1086            result: result.clone(),
1087            left,
1088            right,
1089            ty,
1090        });
1091        result
1092    }
1093
1094    fn mod_(&mut self, left: Value, right: Value, ty: Type) -> Value {
1095        let result = self.new_temp();
1096        self.push_instruction(Instruction::Mod {
1097            result: result.clone(),
1098            left,
1099            right,
1100            ty,
1101        });
1102        result
1103    }
1104
1105    fn pow(&mut self, base: Value, exp: Value) -> Value {
1106        let result = self.new_temp();
1107        self.push_instruction(Instruction::Pow {
1108            result: result.clone(),
1109            base,
1110            exp,
1111        });
1112        result
1113    }
1114
1115    fn and(&mut self, left: Value, right: Value) -> Value {
1116        let result = self.new_temp();
1117        self.push_instruction(Instruction::And {
1118            result: result.clone(),
1119            left,
1120            right,
1121        });
1122        result
1123    }
1124
1125    fn or(&mut self, left: Value, right: Value) -> Value {
1126        let result = self.new_temp();
1127        self.push_instruction(Instruction::Or {
1128            result: result.clone(),
1129            left,
1130            right,
1131        });
1132        result
1133    }
1134
1135    fn xor(&mut self, left: Value, right: Value) -> Value {
1136        let result = self.new_temp();
1137        self.push_instruction(Instruction::Xor {
1138            result: result.clone(),
1139            left,
1140            right,
1141        });
1142        result
1143    }
1144
1145    fn not(&mut self, operand: Value) -> Value {
1146        let result = self.new_temp();
1147        self.push_instruction(Instruction::Not {
1148            result: result.clone(),
1149            operand,
1150        });
1151        result
1152    }
1153
1154    fn shl(&mut self, value: Value, shift: Value) -> Value {
1155        let result = self.new_temp();
1156        self.push_instruction(Instruction::Shl {
1157            result: result.clone(),
1158            value,
1159            shift,
1160        });
1161        result
1162    }
1163
1164    fn shr(&mut self, value: Value, shift: Value) -> Value {
1165        let result = self.new_temp();
1166        self.push_instruction(Instruction::Shr {
1167            result: result.clone(),
1168            value,
1169            shift,
1170        });
1171        result
1172    }
1173
1174    fn sar(&mut self, value: Value, shift: Value) -> Value {
1175        let result = self.new_temp();
1176        self.push_instruction(Instruction::Sar {
1177            result: result.clone(),
1178            value,
1179            shift,
1180        });
1181        result
1182    }
1183
1184    fn eq(&mut self, left: Value, right: Value) -> Value {
1185        let result = self.new_temp();
1186        self.push_instruction(Instruction::Eq {
1187            result: result.clone(),
1188            left,
1189            right,
1190        });
1191        result
1192    }
1193
1194    fn ne(&mut self, left: Value, right: Value) -> Value {
1195        let result = self.new_temp();
1196        self.push_instruction(Instruction::Ne {
1197            result: result.clone(),
1198            left,
1199            right,
1200        });
1201        result
1202    }
1203
1204    fn lt(&mut self, left: Value, right: Value) -> Value {
1205        let result = self.new_temp();
1206        self.push_instruction(Instruction::Lt {
1207            result: result.clone(),
1208            left,
1209            right,
1210        });
1211        result
1212    }
1213
1214    fn gt(&mut self, left: Value, right: Value) -> Value {
1215        let result = self.new_temp();
1216        self.push_instruction(Instruction::Gt {
1217            result: result.clone(),
1218            left,
1219            right,
1220        });
1221        result
1222    }
1223
1224    fn le(&mut self, left: Value, right: Value) -> Value {
1225        let result = self.new_temp();
1226        self.push_instruction(Instruction::Le {
1227            result: result.clone(),
1228            left,
1229            right,
1230        });
1231        result
1232    }
1233
1234    fn ge(&mut self, left: Value, right: Value) -> Value {
1235        let result = self.new_temp();
1236        self.push_instruction(Instruction::Ge {
1237            result: result.clone(),
1238            left,
1239            right,
1240        });
1241        result
1242    }
1243
1244    fn jump(&mut self, target: BlockId, args: Vec<Value>) {
1245        self.push_instruction(Instruction::Jump { target, args });
1246    }
1247
1248    fn branch(
1249        &mut self,
1250        condition: Value,
1251        then_block: BlockId,
1252        else_block: BlockId,
1253        then_args: Vec<Value>,
1254        else_args: Vec<Value>,
1255    ) {
1256        self.push_instruction(Instruction::Branch {
1257            condition,
1258            then_block,
1259            else_block,
1260            then_args,
1261            else_args,
1262        });
1263    }
1264
1265    fn return_value(&mut self, value: Option<Value>) {
1266        self.push_instruction(Instruction::Return { value });
1267    }
1268
1269    fn assign(&mut self, dest: Value, src: Value) {
1270        self.push_instruction(Instruction::Assign {
1271            result: dest,
1272            value: src,
1273        });
1274    }
1275
1276    fn phi(&mut self, values: Vec<(BlockId, Value)>) -> Value {
1277        let result = self.new_temp();
1278        self.push_instruction(Instruction::Phi {
1279            result: result.clone(),
1280            values,
1281        });
1282        result
1283    }
1284}