@@ -8,9 +8,9 @@ use crate::ir::instructions::{CallInfo, InstructionData};
88use crate :: ir:: pcc:: Fact ;
99use crate :: ir:: user_stack_maps:: { UserStackMapEntry , UserStackMapEntryVec } ;
1010use crate :: ir:: {
11- types, Block , BlockCall , ConstantData , ConstantPool , DynamicType , ExtFuncData , FuncRef ,
12- Immediate , Inst , JumpTables , RelSourceLoc , SigRef , Signature , Type , Value ,
13- ValueLabelAssignments , ValueList , ValueListPool ,
11+ types, Block , BlockArg , BlockCall , ConstantData , ConstantPool , DynamicType , ExceptionTables ,
12+ ExtFuncData , FuncRef , Immediate , Inst , JumpTables , RelSourceLoc , SigRef , Signature , Type ,
13+ Value , ValueLabelAssignments , ValueList , ValueListPool ,
1414} ;
1515use crate :: packed_option:: ReservedValue ;
1616use crate :: write:: write_operands;
@@ -158,6 +158,9 @@ pub struct DataFlowGraph {
158158
159159 /// Jump tables used in this function.
160160 pub jump_tables : JumpTables ,
161+
162+ /// Exception tables used in this function.
163+ pub exception_tables : ExceptionTables ,
161164}
162165
163166impl DataFlowGraph {
@@ -178,6 +181,7 @@ impl DataFlowGraph {
178181 constants : ConstantPool :: new ( ) ,
179182 immediates : PrimaryMap :: new ( ) ,
180183 jump_tables : JumpTables :: new ( ) ,
184+ exception_tables : ExceptionTables :: new ( ) ,
181185 }
182186 }
183187
@@ -226,8 +230,12 @@ impl DataFlowGraph {
226230 }
227231
228232 /// Make a BlockCall, bundling together the block and its arguments.
229- pub fn block_call ( & mut self , block : Block , args : & [ Value ] ) -> BlockCall {
230- BlockCall :: new ( block, args, & mut self . value_lists )
233+ pub fn block_call < ' a > (
234+ & mut self ,
235+ block : Block ,
236+ args : impl IntoIterator < Item = & ' a BlockArg > ,
237+ ) -> BlockCall {
238+ BlockCall :: new ( block, args. into_iter ( ) . copied ( ) , & mut self . value_lists )
231239 }
232240
233241 /// Get the total number of values.
@@ -437,13 +445,18 @@ impl DataFlowGraph {
437445
438446 // Rewrite InstructionData in `self.insts`.
439447 for inst in self . insts . 0 . values_mut ( ) {
440- inst. map_values ( & mut self . value_lists , & mut self . jump_tables , |arg| {
441- if let ValueData :: Alias { original, .. } = self . values [ arg] . into ( ) {
442- original
443- } else {
444- arg
445- }
446- } ) ;
448+ inst. map_values (
449+ & mut self . value_lists ,
450+ & mut self . jump_tables ,
451+ & mut self . exception_tables ,
452+ |arg| {
453+ if let ValueData :: Alias { original, .. } = self . values [ arg] . into ( ) {
454+ original
455+ } else {
456+ arg
457+ }
458+ } ,
459+ ) ;
447460 }
448461
449462 // - `results` and block-params in `blocks` are not aliases, by
@@ -843,23 +856,29 @@ impl DataFlowGraph {
843856 & ' dfg self ,
844857 inst : Inst ,
845858 ) -> impl DoubleEndedIterator < Item = Value > + ' dfg {
846- self . inst_args ( inst)
847- . iter ( )
848- . chain (
849- self . insts [ inst]
850- . branch_destination ( & self . jump_tables )
851- . into_iter ( )
852- . flat_map ( |branch| branch. args_slice ( & self . value_lists ) . iter ( ) ) ,
853- )
854- . copied ( )
859+ self . inst_args ( inst) . iter ( ) . copied ( ) . chain (
860+ self . insts [ inst]
861+ . branch_destination ( & self . jump_tables , & self . exception_tables )
862+ . into_iter ( )
863+ . flat_map ( |branch| {
864+ branch
865+ . args ( & self . value_lists )
866+ . filter_map ( |arg| arg. as_value ( ) )
867+ } ) ,
868+ )
855869 }
856870
857871 /// Map a function over the values of the instruction.
858872 pub fn map_inst_values < F > ( & mut self , inst : Inst , body : F )
859873 where
860874 F : FnMut ( Value ) -> Value ,
861875 {
862- self . insts [ inst] . map_values ( & mut self . value_lists , & mut self . jump_tables , body) ;
876+ self . insts [ inst] . map_values (
877+ & mut self . value_lists ,
878+ & mut self . jump_tables ,
879+ & mut self . exception_tables ,
880+ body,
881+ ) ;
863882 }
864883
865884 /// Overwrite the instruction's value references with values from the iterator.
@@ -869,9 +888,12 @@ impl DataFlowGraph {
869888 where
870889 I : Iterator < Item = Value > ,
871890 {
872- self . insts [ inst] . map_values ( & mut self . value_lists , & mut self . jump_tables , |_| {
873- values. next ( ) . unwrap ( )
874- } ) ;
891+ self . insts [ inst] . map_values (
892+ & mut self . value_lists ,
893+ & mut self . jump_tables ,
894+ & mut self . exception_tables ,
895+ |_| values. next ( ) . unwrap ( ) ,
896+ ) ;
875897 }
876898
877899 /// Get all value arguments on `inst` as a slice.
@@ -1078,26 +1100,30 @@ impl DataFlowGraph {
10781100 /// Get the call signature of a direct or indirect call instruction.
10791101 /// Returns `None` if `inst` is not a call instruction.
10801102 pub fn call_signature ( & self , inst : Inst ) -> Option < SigRef > {
1081- match self . insts [ inst] . analyze_call ( & self . value_lists ) {
1103+ match self . insts [ inst] . analyze_call ( & self . value_lists , & self . exception_tables ) {
10821104 CallInfo :: NotACall => None ,
10831105 CallInfo :: Direct ( f, _) => Some ( self . ext_funcs [ f] . signature ) ,
1106+ CallInfo :: DirectWithSig ( _, s, _) => Some ( s) ,
10841107 CallInfo :: Indirect ( s, _) => Some ( s) ,
10851108 }
10861109 }
10871110
1088- /// Like `call_signature` but returns none for tail call instructions.
1089- fn non_tail_call_signature ( & self , inst : Inst ) -> Option < SigRef > {
1111+ /// Like `call_signature` but returns none for tail call
1112+ /// instructions and try-call (exception-handling invoke)
1113+ /// instructions.
1114+ fn non_tail_call_or_try_call_signature ( & self , inst : Inst ) -> Option < SigRef > {
10901115 let sig = self . call_signature ( inst) ?;
10911116 match self . insts [ inst] . opcode ( ) {
10921117 ir:: Opcode :: ReturnCall | ir:: Opcode :: ReturnCallIndirect => None ,
1118+ ir:: Opcode :: TryCall | ir:: Opcode :: TryCallIndirect => None ,
10931119 _ => Some ( sig) ,
10941120 }
10951121 }
10961122
10971123 // Only for use by the verifier. Everyone else should just use
10981124 // `dfg.inst_results(inst).len()`.
10991125 pub ( crate ) fn num_expected_results_for_verifier ( & self , inst : Inst ) -> usize {
1100- match self . non_tail_call_signature ( inst) {
1126+ match self . non_tail_call_or_try_call_signature ( inst) {
11011127 Some ( sig) => self . signatures [ sig] . returns . len ( ) ,
11021128 None => {
11031129 let constraints = self . insts [ inst] . opcode ( ) . constraints ( ) ;
@@ -1112,7 +1138,7 @@ impl DataFlowGraph {
11121138 inst : Inst ,
11131139 ctrl_typevar : Type ,
11141140 ) -> impl iter:: ExactSizeIterator < Item = Type > + ' a {
1115- return match self . non_tail_call_signature ( inst) {
1141+ return match self . non_tail_call_or_try_call_signature ( inst) {
11161142 Some ( sig) => InstResultTypes :: Signature ( self , sig, 0 ) ,
11171143 None => {
11181144 let constraints = self . insts [ inst] . opcode ( ) . constraints ( ) ;
0 commit comments