@@ -88,9 +88,12 @@ should go to.
8888
8989use build:: { BlockAnd , BlockAndExtension , Builder } ;
9090use rustc:: middle:: region:: CodeExtent ;
91- use rustc:: middle:: ty:: Ty ;
91+ use rustc:: middle:: lang_items;
92+ use rustc:: middle:: subst:: Substs ;
93+ use rustc:: middle:: ty:: { Ty , Region } ;
9294use rustc:: mir:: repr:: * ;
93- use syntax:: codemap:: Span ;
95+ use syntax:: codemap:: { Span , DUMMY_SP } ;
96+ use syntax:: parse:: token:: intern_and_get_ident;
9497
9598pub struct Scope < ' tcx > {
9699 extent : CodeExtent ,
@@ -261,13 +264,6 @@ impl<'a,'tcx> Builder<'a,'tcx> {
261264 self . scopes . iter ( ) . rev ( ) . flat_map ( |b| b. cached_block ) . next ( )
262265 }
263266
264- /// Create diverge cleanup and branch to it from `block`.
265- pub fn panic ( & mut self , block : BasicBlock ) {
266- // FIXME: panic terminator should also have conditional cleanup?
267- let cleanup = self . diverge_cleanup ( ) . unwrap_or ( DIVERGE_BLOCK ) ;
268- self . cfg . terminate ( block, Terminator :: Panic { target : cleanup } ) ;
269- }
270-
271267 /// Indicates that `lvalue` should be dropped on exit from
272268 /// `extent`.
273269 pub fn schedule_drop ( & mut self ,
@@ -299,4 +295,94 @@ impl<'a,'tcx> Builder<'a,'tcx> {
299295 pub fn extent_of_outermost_scope ( & self ) -> CodeExtent {
300296 self . scopes . first ( ) . map ( |scope| scope. extent ) . unwrap ( )
301297 }
298+
299+ pub fn panic_bound_check ( & mut self ,
300+ block : BasicBlock ,
301+ index : Operand < ' tcx > ,
302+ len : Operand < ' tcx > ,
303+ span : Span ) {
304+ let cleanup = self . diverge_cleanup ( ) ;
305+ let func = self . lang_function ( lang_items:: PanicBoundsCheckFnLangItem ) ;
306+ let str_ty = self . hir . tcx ( ) . mk_static_str ( ) ;
307+ let tup_ty = self . hir . tcx ( ) . mk_tup ( vec ! [ str_ty, self . hir. tcx( ) . types. u32 ] ) ;
308+ // FIXME: ReStatic might be wrong here?
309+ let ref_region = self . hir . tcx ( ) . mk_region ( Region :: ReStatic ) ;
310+ let ref_ty = self . hir . tcx ( ) . mk_imm_ref ( ref_region, tup_ty. clone ( ) ) ;
311+ let ( file_arg, line_arg) = self . span_to_fileline_args ( span) ;
312+ let ( tuple, tuple_ref) = ( self . temp ( tup_ty) , self . temp ( ref_ty) ) ;
313+ self . cfg . push_assign ( block, DUMMY_SP , & tuple, // tuple = (message_arg, file_arg, line_arg);
314+ Rvalue :: Aggregate ( AggregateKind :: Tuple , vec ! [ file_arg, line_arg] ) ) ;
315+ // FIXME: ReStatic might be wrong here?
316+ self . cfg . push_assign ( block, DUMMY_SP , & tuple_ref, // tuple_ref = &tuple;
317+ Rvalue :: Ref ( * ref_region, BorrowKind :: Unique , tuple) ) ;
318+ self . cfg . terminate ( block, Terminator :: DivergingCall {
319+ func : func,
320+ args : vec ! [ Operand :: Consume ( tuple_ref) , index, len] ,
321+ cleanup : cleanup,
322+ } ) ;
323+ }
324+
325+ /// Create diverge cleanup and branch to it from `block`.
326+ pub fn panic ( & mut self , block : BasicBlock , msg : & ' static str , span : Span ) {
327+ let cleanup = self . diverge_cleanup ( ) ;
328+ let func = self . lang_function ( lang_items:: PanicFnLangItem ) ;
329+
330+ let str_ty = self . hir . tcx ( ) . mk_static_str ( ) ;
331+ let tup_ty = self . hir . tcx ( ) . mk_tup ( vec ! [ str_ty, str_ty, self . hir. tcx( ) . types. u32 ] ) ;
332+ // FIXME: ReStatic might be wrong here?
333+ let ref_region = self . hir . tcx ( ) . mk_region ( Region :: ReStatic ) ;
334+ let ref_ty = self . hir . tcx ( ) . mk_imm_ref ( ref_region, tup_ty. clone ( ) ) ;
335+ let message_arg = Operand :: Constant ( Constant {
336+ span : DUMMY_SP ,
337+ ty : str_ty,
338+ literal : self . hir . str_literal ( intern_and_get_ident ( msg) )
339+ } ) ;
340+ let ( file_arg, line_arg) = self . span_to_fileline_args ( span) ;
341+ let tuple = self . temp ( tup_ty) ;
342+ let tuple_ref = self . temp ( ref_ty) ;
343+ self . cfg . push_assign ( block, DUMMY_SP , & tuple, // tuple = (message_arg, file_arg, line_arg);
344+ Rvalue :: Aggregate ( AggregateKind :: Tuple ,
345+ vec ! [ message_arg, file_arg, line_arg] )
346+ ) ;
347+ // FIXME: ReStatic might be wrong here?
348+ self . cfg . push_assign ( block, DUMMY_SP , & tuple_ref, // tuple_ref = &tuple;
349+ Rvalue :: Ref ( * ref_region, BorrowKind :: Unique , tuple) ) ;
350+
351+ self . cfg . terminate ( block, Terminator :: DivergingCall {
352+ func : func,
353+ args : vec ! [ Operand :: Consume ( tuple_ref) ] ,
354+ cleanup : cleanup,
355+ } ) ;
356+ }
357+
358+ fn lang_function ( & mut self , lang_item : lang_items:: LangItem ) -> Operand < ' tcx > {
359+ let funcdid = match self . hir . tcx ( ) . lang_items . require ( lang_item) {
360+ Ok ( d) => d,
361+ Err ( m) => {
362+ self . hir . tcx ( ) . sess . fatal ( & * m)
363+ }
364+ } ;
365+ Operand :: Constant ( Constant {
366+ span : DUMMY_SP ,
367+ ty : self . hir . tcx ( ) . lookup_item_type ( funcdid) . ty ,
368+ literal : Literal :: Item {
369+ def_id : funcdid,
370+ kind : ItemKind :: Function ,
371+ substs : self . hir . tcx ( ) . mk_substs ( Substs :: empty ( ) )
372+ }
373+ } )
374+ }
375+
376+ fn span_to_fileline_args ( & mut self , span : Span ) -> ( Operand < ' tcx > , Operand < ' tcx > ) {
377+ let span_lines = self . hir . tcx ( ) . sess . codemap ( ) . lookup_char_pos ( span. lo ) ;
378+ ( Operand :: Constant ( Constant {
379+ span : DUMMY_SP ,
380+ ty : self . hir . tcx ( ) . mk_static_str ( ) ,
381+ literal : self . hir . str_literal ( intern_and_get_ident ( & span_lines. file . name ) )
382+ } ) , Operand :: Constant ( Constant {
383+ span : DUMMY_SP ,
384+ ty : self . hir . tcx ( ) . types . u32 ,
385+ literal : self . hir . usize_literal ( span_lines. line )
386+ } ) )
387+ }
302388}
0 commit comments