diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index eaedabc1f54c9..3bcb6e78dce9f 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -199,15 +199,17 @@ pub fn trans_mir<'a, 'tcx: 'a>( debug!("fn_ty: {:?}", fn_ty); let debug_context = debuginfo::create_function_debug_context(ccx, instance, sig, llfn, mir); - let bcx = Builder::new_block(ccx, llfn, "entry-block"); + let bcx = Builder::new_block(ccx, llfn, "start"); let cleanup_kinds = analyze::cleanup_kinds(&mir); - // Allocate a `Block` for every basic block + // Allocate a `Block` for every basic block, except + // the start block, if nothing loops back to it. + let reentrant_start_block = !mir.predecessors_for(mir::START_BLOCK).is_empty(); let block_bcxs: IndexVec = mir.basic_blocks().indices().map(|bb| { - if bb == mir::START_BLOCK { - bcx.build_sibling_block("start").llbb() + if bb == mir::START_BLOCK && !reentrant_start_block { + bcx.llbb() } else { bcx.build_sibling_block(&format!("{:?}", bb)).llbb() } @@ -294,9 +296,10 @@ pub fn trans_mir<'a, 'tcx: 'a>( .collect() }; - // Branch to the START block - let start_bcx = mircx.blocks[mir::START_BLOCK]; - bcx.br(start_bcx); + // Branch to the START block, if it's not the entry block. + if reentrant_start_block { + bcx.br(mircx.blocks[mir::START_BLOCK]); + } // Up until here, IR instructions for this function have explicitly not been annotated with // source code location, so we don't step into call setup code. From here on, source location diff --git a/src/test/codegen/naked-functions.rs b/src/test/codegen/naked-functions.rs index 9de74f72005e3..9883ca6b35d04 100644 --- a/src/test/codegen/naked-functions.rs +++ b/src/test/codegen/naked-functions.rs @@ -20,7 +20,8 @@ #[no_mangle] #[naked] fn naked_empty() { - // CHECK: ret void + // CHECK-NEXT: {{.+}}: + // CHECK-NEXT: ret void } // CHECK: Function Attrs: naked uwtable @@ -28,9 +29,10 @@ fn naked_empty() { #[naked] // CHECK-NEXT: define internal void @naked_with_args(i{{[0-9]+}}) fn naked_with_args(a: isize) { - // CHECK: %a = alloca i{{[0-9]+}} - // CHECK: ret void + // CHECK-NEXT: {{.+}}: + // CHECK-NEXT: %a = alloca i{{[0-9]+}} &a; // keep variable in an alloca + // CHECK: ret void } // CHECK: Function Attrs: naked uwtable @@ -38,7 +40,8 @@ fn naked_with_args(a: isize) { #[no_mangle] #[naked] fn naked_with_return() -> isize { - // CHECK: ret i{{[0-9]+}} 0 + // CHECK-NEXT: {{.+}}: + // CHECK-NEXT: ret i{{[0-9]+}} 0 0 } @@ -47,9 +50,10 @@ fn naked_with_return() -> isize { #[no_mangle] #[naked] fn naked_with_args_and_return(a: isize) -> isize { - // CHECK: %a = alloca i{{[0-9]+}} - // CHECK: ret i{{[0-9]+}} %{{[0-9]+}} + // CHECK-NEXT: {{.+}}: + // CHECK-NEXT: %a = alloca i{{[0-9]+}} &a; // keep variable in an alloca + // CHECK: ret i{{[0-9]+}} %{{[0-9]+}} a } @@ -58,14 +62,37 @@ fn naked_with_args_and_return(a: isize) -> isize { #[no_mangle] #[naked] fn naked_recursive() { - // CHECK: call void @naked_empty() + // CHECK-NEXT: {{.+}}: + // CHECK-NEXT: call void @naked_empty() + + // FIXME(#39685) Avoid one block per call. + // CHECK-NEXT: br label %bb1 + // CHECK: bb1: + naked_empty(); - // CHECK: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_return() + + // CHECK-NEXT: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_return() + + // FIXME(#39685) Avoid one block per call. + // CHECK-NEXT: br label %bb2 + // CHECK: bb2: + + // CHECK-NEXT: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}} %{{[0-9]+}}) + + // FIXME(#39685) Avoid one block per call. + // CHECK-NEXT: br label %bb3 + // CHECK: bb3: + + // CHECK-NEXT: call void @naked_with_args(i{{[0-9]+}} %{{[0-9]+}}) + + // FIXME(#39685) Avoid one block per call. + // CHECK-NEXT: br label %bb4 + // CHECK: bb4: + naked_with_args( - // CHECK: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}} %{{[0-9]+}}) naked_with_args_and_return( - // CHECK: call void @naked_with_args(i{{[0-9]+}} %{{[0-9]+}}) naked_with_return() ) ); + // CHECK-NEXT: ret void }