From e6d7a8d7d406e82357f3a1675e94a3ac697e0e8e Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 18 Feb 2022 15:10:56 +0100 Subject: [PATCH 1/4] Remove build_sibling_block --- compiler/rustc_codegen_gcc/src/builder.rs | 21 ++++------ compiler/rustc_codegen_llvm/src/builder.rs | 24 +++++------ compiler/rustc_codegen_llvm/src/intrinsic.rs | 42 ++++++++++++------- compiler/rustc_codegen_llvm/src/va_arg.rs | 20 +++++---- compiler/rustc_codegen_ssa/src/mir/block.rs | 18 ++++---- .../rustc_codegen_ssa/src/traits/builder.rs | 3 -- 6 files changed, 68 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index ffb77e16a14..a576291cd51 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -390,11 +390,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { bx } - fn build_sibling_block(&mut self, name: &str) -> Self { - let block = self.append_sibling_block(name); - Self::build(self.cx, block) - } - fn llbb(&self) -> Block<'gcc> { self.block.expect("block") } @@ -880,28 +875,30 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let start = dest.project_index(&mut self, zero).llval; let end = dest.project_index(&mut self, count).llval; - let mut header_bx = self.build_sibling_block("repeat_loop_header"); - let mut body_bx = self.build_sibling_block("repeat_loop_body"); - let next_bx = self.build_sibling_block("repeat_loop_next"); + let header_bb = self.append_sibling_block("repeat_loop_header"); + let body_bb = self.append_sibling_block("repeat_loop_body"); + let next_bb = self.append_sibling_block("repeat_loop_next"); let ptr_type = start.get_type(); let current = self.llbb().get_function().new_local(None, ptr_type, "loop_var"); let current_val = current.to_rvalue(); self.assign(current, start); - self.br(header_bx.llbb()); + self.br(header_bb); + let mut header_bx = Builder::build(self.cx, header_bb); let keep_going = header_bx.icmp(IntPredicate::IntNE, current_val, end); - header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb()); + header_bx.cond_br(keep_going, body_bb, next_bb); + let mut body_bx = Builder::build(self.cx, body_bb); let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size); cg_elem.val.store(&mut body_bx, PlaceRef::new_sized_aligned(current_val, cg_elem.layout, align)); let next = body_bx.inbounds_gep(self.backend_type(cg_elem.layout), current.to_rvalue(), &[self.const_usize(1)]); body_bx.llbb().add_assignment(None, current, next); - body_bx.br(header_bx.llbb()); + body_bx.br(header_bb); - next_bx + Builder::build(self.cx, next_bb) } fn range_metadata(&mut self, _load: RValue<'gcc>, _range: WrappingRange) { diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index c9a04e6280f..478cc3c06f6 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -166,11 +166,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { Self::append_block(self.cx, self.llfn(), name) } - fn build_sibling_block(&mut self, name: &str) -> Self { - let llbb = self.append_sibling_block(name); - Self::build(self.cx, llbb) - } - fn ret_void(&mut self) { unsafe { llvm::LLVMBuildRetVoid(self.llbuilder); @@ -544,16 +539,19 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let start = dest.project_index(&mut self, zero).llval; let end = dest.project_index(&mut self, count).llval; - let mut header_bx = self.build_sibling_block("repeat_loop_header"); - let mut body_bx = self.build_sibling_block("repeat_loop_body"); - let next_bx = self.build_sibling_block("repeat_loop_next"); + let header_bb = self.append_sibling_block("repeat_loop_header"); + let body_bb = self.append_sibling_block("repeat_loop_body"); + let next_bb = self.append_sibling_block("repeat_loop_next"); - self.br(header_bx.llbb()); + self.br(header_bb); + + let mut header_bx = Self::build(self.cx, header_bb); let current = header_bx.phi(self.val_ty(start), &[start], &[self.llbb()]); let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end); - header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb()); + header_bx.cond_br(keep_going, body_bb, next_bb); + let mut body_bx = Self::build(self.cx, body_bb); let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size); cg_elem .val @@ -564,10 +562,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { current, &[self.const_usize(1)], ); - body_bx.br(header_bx.llbb()); - header_bx.add_incoming_to_phi(current, next, body_bx.llbb()); + body_bx.br(header_bb); + header_bx.add_incoming_to_phi(current, next, body_bb); - next_bx + Self::build(self.cx, next_bb) } fn range_metadata(&mut self, load: &'ll Value, range: WrappingRange) { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index f471f461e86..b5c5148d51a 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -452,11 +452,11 @@ fn codegen_msvc_try<'ll>( let (llty, llfn) = get_rust_try_fn(bx, &mut |mut bx| { bx.set_personality_fn(bx.eh_personality()); - let mut normal = bx.build_sibling_block("normal"); - let mut catchswitch = bx.build_sibling_block("catchswitch"); - let mut catchpad_rust = bx.build_sibling_block("catchpad_rust"); - let mut catchpad_foreign = bx.build_sibling_block("catchpad_foreign"); - let mut caught = bx.build_sibling_block("caught"); + let normal = bx.append_sibling_block("normal"); + let catchswitch = bx.append_sibling_block("catchswitch"); + let catchpad_rust = bx.append_sibling_block("catchpad_rust"); + let catchpad_foreign = bx.append_sibling_block("catchpad_foreign"); + let caught = bx.append_sibling_block("caught"); let try_func = llvm::get_param(bx.llfn(), 0); let data = llvm::get_param(bx.llfn(), 1); @@ -520,12 +520,13 @@ fn codegen_msvc_try<'ll>( let ptr_align = bx.tcx().data_layout.pointer_align.abi; let slot = bx.alloca(bx.type_i8p(), ptr_align); let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void()); - bx.invoke(try_func_ty, try_func, &[data], normal.llbb(), catchswitch.llbb(), None); + bx.invoke(try_func_ty, try_func, &[data], normal, catchswitch, None); + let mut normal = Builder::build(bx.cx, normal); normal.ret(bx.const_i32(0)); - let cs = - catchswitch.catch_switch(None, None, &[catchpad_rust.llbb(), catchpad_foreign.llbb()]); + let mut catchswitch = Builder::build(bx.cx, catchswitch); + let cs = catchswitch.catch_switch(None, None, &[catchpad_rust, catchpad_foreign]); // We can't use the TypeDescriptor defined in libpanic_unwind because it // might be in another DLL and the SEH encoding only supports specifying @@ -558,20 +559,23 @@ fn codegen_msvc_try<'ll>( // since our exception object effectively contains a Box. // // Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang + let mut catchpad_rust = Builder::build(bx.cx, catchpad_rust); let flags = bx.const_i32(8); let funclet = catchpad_rust.catch_pad(cs, &[tydesc, flags, slot]); let ptr = catchpad_rust.load(bx.type_i8p(), slot, ptr_align); let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void()); catchpad_rust.call(catch_ty, catch_func, &[data, ptr], Some(&funclet)); - catchpad_rust.catch_ret(&funclet, caught.llbb()); + catchpad_rust.catch_ret(&funclet, caught); // The flag value of 64 indicates a "catch-all". + let mut catchpad_foreign = Builder::build(bx.cx, catchpad_foreign); let flags = bx.const_i32(64); let null = bx.const_null(bx.type_i8p()); let funclet = catchpad_foreign.catch_pad(cs, &[null, flags, null]); catchpad_foreign.call(catch_ty, catch_func, &[data, null], Some(&funclet)); - catchpad_foreign.catch_ret(&funclet, caught.llbb()); + catchpad_foreign.catch_ret(&funclet, caught); + let mut caught = Builder::build(bx.cx, caught); caught.ret(bx.const_i32(1)); }); @@ -613,14 +617,16 @@ fn codegen_gnu_try<'ll>( // (%ptr, _) = landingpad // call %catch_func(%data, %ptr) // ret 1 - let mut then = bx.build_sibling_block("then"); - let mut catch = bx.build_sibling_block("catch"); + let then = bx.append_sibling_block("then"); + let catch = bx.append_sibling_block("catch"); let try_func = llvm::get_param(bx.llfn(), 0); let data = llvm::get_param(bx.llfn(), 1); let catch_func = llvm::get_param(bx.llfn(), 2); let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void()); - bx.invoke(try_func_ty, try_func, &[data], then.llbb(), catch.llbb(), None); + bx.invoke(try_func_ty, try_func, &[data], then, catch, None); + + let mut then = Builder::build(bx.cx, then); then.ret(bx.const_i32(0)); // Type indicator for the exception being thrown. @@ -629,6 +635,7 @@ fn codegen_gnu_try<'ll>( // being thrown. The second value is a "selector" indicating which of // the landing pad clauses the exception's type had been matched to. // rust_try ignores the selector. + let mut catch = Builder::build(bx.cx, catch); let lpad_ty = bx.type_struct(&[bx.type_i8p(), bx.type_i32()], false); let vals = catch.landing_pad(lpad_ty, bx.eh_personality(), 1); let tydesc = bx.const_null(bx.type_i8p()); @@ -674,14 +681,16 @@ fn codegen_emcc_try<'ll>( // %catch_data[1] = %is_rust_panic // call %catch_func(%data, %catch_data) // ret 1 - let mut then = bx.build_sibling_block("then"); - let mut catch = bx.build_sibling_block("catch"); + let then = bx.append_sibling_block("then"); + let catch = bx.append_sibling_block("catch"); let try_func = llvm::get_param(bx.llfn(), 0); let data = llvm::get_param(bx.llfn(), 1); let catch_func = llvm::get_param(bx.llfn(), 2); let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void()); - bx.invoke(try_func_ty, try_func, &[data], then.llbb(), catch.llbb(), None); + bx.invoke(try_func_ty, try_func, &[data], then, catch, None); + + let mut then = Builder::build(bx.cx, then); then.ret(bx.const_i32(0)); // Type indicator for the exception being thrown. @@ -689,6 +698,7 @@ fn codegen_emcc_try<'ll>( // The first value in this tuple is a pointer to the exception object // being thrown. The second value is a "selector" indicating which of // the landing pad clauses the exception's type had been matched to. + let mut catch = Builder::build(bx.cx, catch); let tydesc = bx.eh_catch_typeinfo(); let lpad_ty = bx.type_struct(&[bx.type_i8p(), bx.type_i32()], false); let vals = catch.landing_pad(lpad_ty, bx.eh_personality(), 2); diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index f090ae6ecb4..13d9a47b106 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -102,10 +102,10 @@ fn emit_aapcs_va_arg<'ll, 'tcx>( let va_list_ty = va_list_layout.llvm_type(bx); let layout = bx.cx.layout_of(target_ty); - let mut maybe_reg = bx.build_sibling_block("va_arg.maybe_reg"); - let mut in_reg = bx.build_sibling_block("va_arg.in_reg"); - let mut on_stack = bx.build_sibling_block("va_arg.on_stack"); - let mut end = bx.build_sibling_block("va_arg.end"); + let maybe_reg = bx.append_sibling_block("va_arg.maybe_reg"); + let in_reg = bx.append_sibling_block("va_arg.in_reg"); + let on_stack = bx.append_sibling_block("va_arg.on_stack"); + let end = bx.append_sibling_block("va_arg.end"); let zero = bx.const_i32(0); let offset_align = Align::from_bytes(4).unwrap(); @@ -125,12 +125,13 @@ fn emit_aapcs_va_arg<'ll, 'tcx>( // if the offset >= 0 then the value will be on the stack let mut reg_off_v = bx.load(bx.type_i32(), reg_off, offset_align); let use_stack = bx.icmp(IntPredicate::IntSGE, reg_off_v, zero); - bx.cond_br(use_stack, on_stack.llbb(), maybe_reg.llbb()); + bx.cond_br(use_stack, on_stack, maybe_reg); // The value at this point might be in a register, but there is a chance that // it could be on the stack so we have to update the offset and then check // the offset again. + let mut maybe_reg = Builder::build(bx.cx, maybe_reg); if gr_type && layout.align.abi.bytes() > 8 { reg_off_v = maybe_reg.add(reg_off_v, bx.const_i32(15)); reg_off_v = maybe_reg.and(reg_off_v, bx.const_i32(-16)); @@ -142,8 +143,9 @@ fn emit_aapcs_va_arg<'ll, 'tcx>( // Check to see if we have overflowed the registers as a result of this. // If we have then we need to use the stack for this value let use_stack = maybe_reg.icmp(IntPredicate::IntSGT, new_reg_off_v, zero); - maybe_reg.cond_br(use_stack, on_stack.llbb(), in_reg.llbb()); + maybe_reg.cond_br(use_stack, on_stack, in_reg); + let mut in_reg = Builder::build(bx.cx, in_reg); let top_type = bx.type_i8p(); let top = in_reg.struct_gep(va_list_ty, va_list_addr, reg_top_index); let top = in_reg.load(top_type, top, bx.tcx().data_layout.pointer_align.abi); @@ -158,13 +160,15 @@ fn emit_aapcs_va_arg<'ll, 'tcx>( let reg_type = layout.llvm_type(bx); let reg_addr = in_reg.bitcast(reg_addr, bx.cx.type_ptr_to(reg_type)); let reg_value = in_reg.load(reg_type, reg_addr, layout.align.abi); - in_reg.br(end.llbb()); + in_reg.br(end); // On Stack block + let mut on_stack = Builder::build(bx.cx, on_stack); let stack_value = emit_ptr_va_arg(&mut on_stack, list, target_ty, false, Align::from_bytes(8).unwrap(), true); - on_stack.br(end.llbb()); + on_stack.br(end); + let mut end = Builder::build(bx.cx, end); let val = end.phi( layout.immediate_llvm_type(bx), &[reg_value, stack_value], diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 33f883f9b6c..1979bbdb859 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -452,15 +452,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Create the failure block and the conditional branch to it. let lltarget = helper.llblock(self, target); - let panic_block = bx.build_sibling_block("panic"); + let panic_block = bx.append_sibling_block("panic"); if expected { - bx.cond_br(cond, lltarget, panic_block.llbb()); + bx.cond_br(cond, lltarget, panic_block); } else { - bx.cond_br(cond, panic_block.llbb(), lltarget); + bx.cond_br(cond, panic_block, lltarget); } // After this point, bx is the block for the call to panic. - bx = panic_block; + bx = Bx::build(self.cx, panic_block); self.set_debug_loc(&mut bx, terminator.source_info); // Get the location information. @@ -908,10 +908,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Test whether the function pointer is associated with the type identifier. let cond = bx.type_test(fn_ptr, typeid_metadata); - let mut bx_pass = bx.build_sibling_block("type_test.pass"); - let mut bx_fail = bx.build_sibling_block("type_test.fail"); - bx.cond_br(cond, bx_pass.llbb(), bx_fail.llbb()); + let bb_pass = bx.append_sibling_block("type_test.pass"); + let bb_fail = bx.append_sibling_block("type_test.fail"); + bx.cond_br(cond, bb_pass, bb_fail); + let mut bx_pass = Bx::build(self.cx, bb_pass); helper.do_call( self, &mut bx_pass, @@ -922,6 +923,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cleanup, ); + let mut bx_fail = Bx::build(self.cx, bb_fail); bx_fail.abort(); bx_fail.unreachable(); @@ -1441,7 +1443,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }) } - // FIXME(eddyb) replace with `build_sibling_block`/`append_sibling_block` + // FIXME(eddyb) replace with `append_sibling_block` // (which requires having a `Bx` already, and not all callers do). fn new_block(&self, name: &str) -> Bx { let llbb = Bx::append_block(self.cx, self.llfn, name); diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 53fb21b269a..6c7162c68d4 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -53,9 +53,6 @@ pub trait BuilderMethods<'a, 'tcx>: fn append_sibling_block(&mut self, name: &str) -> Self::BasicBlock; - // FIXME(eddyb) replace with callers using `append_sibling_block`. - fn build_sibling_block(&mut self, name: &str) -> Self; - fn ret_void(&mut self); fn ret(&mut self, v: Self::Value); fn br(&mut self, dest: Self::BasicBlock); From e142cdf4f6c3d18cb8f2f9ecfa386873a1910050 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 18 Feb 2022 15:20:19 +0100 Subject: [PATCH 2/4] Remove FunctionCx::new_block --- compiler/rustc_codegen_ssa/src/mir/block.rs | 46 +++++++++++---------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 1979bbdb859..f3d41f3f86c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -96,9 +96,10 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { debug!("llblock: creating cleanup trampoline for {:?}", target); let name = &format!("{:?}_cleanup_trampoline_{:?}", self.bb, target); - let mut trampoline = fx.new_block(name); - trampoline.cleanup_ret(self.funclet(fx).unwrap(), Some(lltarget)); - trampoline.llbb() + let trampoline = Bx::append_block(fx.cx, fx.llfn, name); + let mut trampoline_bx = Bx::build(fx.cx, trampoline); + trampoline_bx.cleanup_ret(self.funclet(fx).unwrap(), Some(lltarget)); + trampoline } else { lltarget } @@ -1358,16 +1359,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // bar(); // } Some(&mir::TerminatorKind::Abort) => { - let mut cs_bx = self.new_block(&format!("cs_funclet{:?}", bb)); - let mut cp_bx = self.new_block(&format!("cp_funclet{:?}", bb)); - ret_llbb = cs_bx.llbb(); + let cs_bb = + Bx::append_block(self.cx, self.llfn, &format!("cs_funclet{:?}", bb)); + let cp_bb = + Bx::append_block(self.cx, self.llfn, &format!("cp_funclet{:?}", bb)); + ret_llbb = cs_bb; - let cs = cs_bx.catch_switch(None, None, &[cp_bx.llbb()]); + let mut cs_bx = Bx::build(self.cx, cs_bb); + let cs = cs_bx.catch_switch(None, None, &[cp_bb]); // The "null" here is actually a RTTI type descriptor for the // C++ personality function, but `catch (...)` has no type so // it's null. The 64 here is actually a bitfield which // represents that this is a catch-all block. + let mut cp_bx = Bx::build(self.cx, cp_bb); let null = cp_bx.const_null( cp_bx.type_i8p_ext(cp_bx.cx().data_layout().instruction_address_space), ); @@ -1376,8 +1381,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cp_bx.br(llbb); } _ => { - let mut cleanup_bx = self.new_block(&format!("funclet_{:?}", bb)); - ret_llbb = cleanup_bx.llbb(); + let cleanup_bb = + Bx::append_block(self.cx, self.llfn, &format!("funclet_{:?}", bb)); + ret_llbb = cleanup_bb; + let mut cleanup_bx = Bx::build(self.cx, cleanup_bb); funclet = cleanup_bx.cleanup_pad(None, &[]); cleanup_bx.br(llbb); } @@ -1385,7 +1392,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.funclets[bb] = Some(funclet); ret_llbb } else { - let mut bx = self.new_block("cleanup"); + let bb = Bx::append_block(self.cx, self.llfn, "cleanup"); + let mut bx = Bx::build(self.cx, bb); let llpersonality = self.cx.eh_personality(); let llretty = self.landing_pad_type(); @@ -1407,10 +1415,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn unreachable_block(&mut self) -> Bx::BasicBlock { self.unreachable_block.unwrap_or_else(|| { - let mut bx = self.new_block("unreachable"); + let llbb = Bx::append_block(self.cx, self.llfn, "unreachable"); + let mut bx = Bx::build(self.cx, llbb); bx.unreachable(); - self.unreachable_block = Some(bx.llbb()); - bx.llbb() + self.unreachable_block = Some(llbb); + llbb }) } @@ -1418,7 +1427,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.double_unwind_guard.unwrap_or_else(|| { assert!(!base::wants_msvc_seh(self.cx.sess())); - let mut bx = self.new_block("abort"); + let llbb = Bx::append_block(self.cx, self.llfn, "abort"); + let mut bx = Bx::build(self.cx, llbb); self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span)); let llpersonality = self.cx.eh_personality(); @@ -1436,20 +1446,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.apply_attrs_to_cleanup_callsite(llret); bx.unreachable(); - let llbb = bx.llbb(); self.double_unwind_guard = Some(llbb); llbb }) } - // FIXME(eddyb) replace with `append_sibling_block` - // (which requires having a `Bx` already, and not all callers do). - fn new_block(&self, name: &str) -> Bx { - let llbb = Bx::append_block(self.cx, self.llfn, name); - Bx::build(self.cx, llbb) - } - /// Get the backend `BasicBlock` for a MIR `BasicBlock`, either already /// cached in `self.cached_llbbs`, or created on demand (and cached). // FIXME(eddyb) rename `llbb` and other `ll`-prefixed things to use a From 0edcf1e2496caed074187c3c5ffac14537e633cf Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 18 Feb 2022 15:38:27 +0100 Subject: [PATCH 3/4] Inline build_block --- compiler/rustc_codegen_ssa/src/mir/block.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index f3d41f3f86c..ca46d230b72 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -170,7 +170,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } if let Some((ret_dest, target)) = destination { - let mut ret_bx = fx.build_block(target); + let target_llbb = fx.llbb(target); + let mut ret_bx = Bx::build(fx.cx, target_llbb); fx.set_debug_loc(&mut ret_bx, self.terminator.source_info); fx.store_return(&mut ret_bx, ret_dest, &fn_abi.ret, invokeret); } @@ -1023,7 +1024,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_block(&mut self, bb: mir::BasicBlock) { - let mut bx = self.build_block(bb); + let llbb = self.llbb(bb); + let mut bx = Bx::build(self.cx, llbb); let mir = self.mir; let data = &mir[bb]; @@ -1465,11 +1467,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }) } - pub fn build_block(&mut self, bb: mir::BasicBlock) -> Bx { - let llbb = self.llbb(bb); - Bx::build(self.cx, llbb) - } - fn make_return_dest( &mut self, bx: &mut Bx, From 96cf7999ab64ead0c06384da51eb8586ffebfc1e Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 18 Feb 2022 15:37:31 +0100 Subject: [PATCH 4/4] Introduce Bx::switch_to_block --- compiler/rustc_codegen_gcc/src/builder.rs | 24 +++-- compiler/rustc_codegen_llvm/src/builder.rs | 4 + compiler/rustc_codegen_llvm/src/intrinsic.rs | 94 +++++++++---------- compiler/rustc_codegen_llvm/src/va_arg.rs | 46 +++++---- compiler/rustc_codegen_ssa/src/mir/block.rs | 19 ++-- .../rustc_codegen_ssa/src/traits/builder.rs | 2 + 6 files changed, 95 insertions(+), 94 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index a576291cd51..b430dc329cb 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -404,6 +404,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { func.new_block(name) } + fn switch_to_block(&mut self, block: Self::BasicBlock) { + *self.cx.current_block.borrow_mut() = Some(block); + self.block = Some(block); + } + fn ret_void(&mut self) { self.llbb().end_with_void_return(None) } @@ -886,19 +891,20 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { self.br(header_bb); - let mut header_bx = Builder::build(self.cx, header_bb); - let keep_going = header_bx.icmp(IntPredicate::IntNE, current_val, end); - header_bx.cond_br(keep_going, body_bb, next_bb); + self.switch_to_block(header_bb); + let keep_going = self.icmp(IntPredicate::IntNE, current_val, end); + self.cond_br(keep_going, body_bb, next_bb); - let mut body_bx = Builder::build(self.cx, body_bb); + self.switch_to_block(body_bb); let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size); - cg_elem.val.store(&mut body_bx, PlaceRef::new_sized_aligned(current_val, cg_elem.layout, align)); + cg_elem.val.store(&mut self, PlaceRef::new_sized_aligned(current_val, cg_elem.layout, align)); - let next = body_bx.inbounds_gep(self.backend_type(cg_elem.layout), current.to_rvalue(), &[self.const_usize(1)]); - body_bx.llbb().add_assignment(None, current, next); - body_bx.br(header_bb); + let next = self.inbounds_gep(self.backend_type(cg_elem.layout), current.to_rvalue(), &[self.const_usize(1)]); + self.llbb().add_assignment(None, current, next); + self.br(header_bb); - Builder::build(self.cx, next_bb) + self.switch_to_block(next_bb); + self } fn range_metadata(&mut self, _load: RValue<'gcc>, _range: WrappingRange) { diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 478cc3c06f6..780af5bc2af 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -166,6 +166,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { Self::append_block(self.cx, self.llfn(), name) } + fn switch_to_block(&mut self, llbb: Self::BasicBlock) { + *self = Self::build(self.cx, llbb) + } + fn ret_void(&mut self) { unsafe { llvm::LLVMBuildRetVoid(self.llbuilder); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index b5c5148d51a..e7c13e793d9 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -522,11 +522,11 @@ fn codegen_msvc_try<'ll>( let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void()); bx.invoke(try_func_ty, try_func, &[data], normal, catchswitch, None); - let mut normal = Builder::build(bx.cx, normal); - normal.ret(bx.const_i32(0)); + bx.switch_to_block(normal); + bx.ret(bx.const_i32(0)); - let mut catchswitch = Builder::build(bx.cx, catchswitch); - let cs = catchswitch.catch_switch(None, None, &[catchpad_rust, catchpad_foreign]); + bx.switch_to_block(catchswitch); + let cs = bx.catch_switch(None, None, &[catchpad_rust, catchpad_foreign]); // We can't use the TypeDescriptor defined in libpanic_unwind because it // might be in another DLL and the SEH encoding only supports specifying @@ -559,24 +559,24 @@ fn codegen_msvc_try<'ll>( // since our exception object effectively contains a Box. // // Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang - let mut catchpad_rust = Builder::build(bx.cx, catchpad_rust); + bx.switch_to_block(catchpad_rust); let flags = bx.const_i32(8); - let funclet = catchpad_rust.catch_pad(cs, &[tydesc, flags, slot]); - let ptr = catchpad_rust.load(bx.type_i8p(), slot, ptr_align); + let funclet = bx.catch_pad(cs, &[tydesc, flags, slot]); + let ptr = bx.load(bx.type_i8p(), slot, ptr_align); let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void()); - catchpad_rust.call(catch_ty, catch_func, &[data, ptr], Some(&funclet)); - catchpad_rust.catch_ret(&funclet, caught); + bx.call(catch_ty, catch_func, &[data, ptr], Some(&funclet)); + bx.catch_ret(&funclet, caught); // The flag value of 64 indicates a "catch-all". - let mut catchpad_foreign = Builder::build(bx.cx, catchpad_foreign); + bx.switch_to_block(catchpad_foreign); let flags = bx.const_i32(64); let null = bx.const_null(bx.type_i8p()); - let funclet = catchpad_foreign.catch_pad(cs, &[null, flags, null]); - catchpad_foreign.call(catch_ty, catch_func, &[data, null], Some(&funclet)); - catchpad_foreign.catch_ret(&funclet, caught); + let funclet = bx.catch_pad(cs, &[null, flags, null]); + bx.call(catch_ty, catch_func, &[data, null], Some(&funclet)); + bx.catch_ret(&funclet, caught); - let mut caught = Builder::build(bx.cx, caught); - caught.ret(bx.const_i32(1)); + bx.switch_to_block(caught); + bx.ret(bx.const_i32(1)); }); // Note that no invoke is used here because by definition this function @@ -626,8 +626,8 @@ fn codegen_gnu_try<'ll>( let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void()); bx.invoke(try_func_ty, try_func, &[data], then, catch, None); - let mut then = Builder::build(bx.cx, then); - then.ret(bx.const_i32(0)); + bx.switch_to_block(then); + bx.ret(bx.const_i32(0)); // Type indicator for the exception being thrown. // @@ -635,15 +635,15 @@ fn codegen_gnu_try<'ll>( // being thrown. The second value is a "selector" indicating which of // the landing pad clauses the exception's type had been matched to. // rust_try ignores the selector. - let mut catch = Builder::build(bx.cx, catch); + bx.switch_to_block(catch); let lpad_ty = bx.type_struct(&[bx.type_i8p(), bx.type_i32()], false); - let vals = catch.landing_pad(lpad_ty, bx.eh_personality(), 1); + let vals = bx.landing_pad(lpad_ty, bx.eh_personality(), 1); let tydesc = bx.const_null(bx.type_i8p()); - catch.add_clause(vals, tydesc); - let ptr = catch.extract_value(vals, 0); + bx.add_clause(vals, tydesc); + let ptr = bx.extract_value(vals, 0); let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void()); - catch.call(catch_ty, catch_func, &[data, ptr], None); - catch.ret(bx.const_i32(1)); + bx.call(catch_ty, catch_func, &[data, ptr], None); + bx.ret(bx.const_i32(1)); }); // Note that no invoke is used here because by definition this function @@ -690,51 +690,45 @@ fn codegen_emcc_try<'ll>( let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void()); bx.invoke(try_func_ty, try_func, &[data], then, catch, None); - let mut then = Builder::build(bx.cx, then); - then.ret(bx.const_i32(0)); + bx.switch_to_block(then); + bx.ret(bx.const_i32(0)); // Type indicator for the exception being thrown. // // The first value in this tuple is a pointer to the exception object // being thrown. The second value is a "selector" indicating which of // the landing pad clauses the exception's type had been matched to. - let mut catch = Builder::build(bx.cx, catch); + bx.switch_to_block(catch); let tydesc = bx.eh_catch_typeinfo(); let lpad_ty = bx.type_struct(&[bx.type_i8p(), bx.type_i32()], false); - let vals = catch.landing_pad(lpad_ty, bx.eh_personality(), 2); - catch.add_clause(vals, tydesc); - catch.add_clause(vals, bx.const_null(bx.type_i8p())); - let ptr = catch.extract_value(vals, 0); - let selector = catch.extract_value(vals, 1); + let vals = bx.landing_pad(lpad_ty, bx.eh_personality(), 2); + bx.add_clause(vals, tydesc); + bx.add_clause(vals, bx.const_null(bx.type_i8p())); + let ptr = bx.extract_value(vals, 0); + let selector = bx.extract_value(vals, 1); // Check if the typeid we got is the one for a Rust panic. - let rust_typeid = catch.call_intrinsic("llvm.eh.typeid.for", &[tydesc]); - let is_rust_panic = catch.icmp(IntPredicate::IntEQ, selector, rust_typeid); - let is_rust_panic = catch.zext(is_rust_panic, bx.type_bool()); + let rust_typeid = bx.call_intrinsic("llvm.eh.typeid.for", &[tydesc]); + let is_rust_panic = bx.icmp(IntPredicate::IntEQ, selector, rust_typeid); + let is_rust_panic = bx.zext(is_rust_panic, bx.type_bool()); // We need to pass two values to catch_func (ptr and is_rust_panic), so // create an alloca and pass a pointer to that. let ptr_align = bx.tcx().data_layout.pointer_align.abi; let i8_align = bx.tcx().data_layout.i8_align.abi; let catch_data_type = bx.type_struct(&[bx.type_i8p(), bx.type_bool()], false); - let catch_data = catch.alloca(catch_data_type, ptr_align); - let catch_data_0 = catch.inbounds_gep( - catch_data_type, - catch_data, - &[bx.const_usize(0), bx.const_usize(0)], - ); - catch.store(ptr, catch_data_0, ptr_align); - let catch_data_1 = catch.inbounds_gep( - catch_data_type, - catch_data, - &[bx.const_usize(0), bx.const_usize(1)], - ); - catch.store(is_rust_panic, catch_data_1, i8_align); - let catch_data = catch.bitcast(catch_data, bx.type_i8p()); + let catch_data = bx.alloca(catch_data_type, ptr_align); + let catch_data_0 = + bx.inbounds_gep(catch_data_type, catch_data, &[bx.const_usize(0), bx.const_usize(0)]); + bx.store(ptr, catch_data_0, ptr_align); + let catch_data_1 = + bx.inbounds_gep(catch_data_type, catch_data, &[bx.const_usize(0), bx.const_usize(1)]); + bx.store(is_rust_panic, catch_data_1, i8_align); + let catch_data = bx.bitcast(catch_data, bx.type_i8p()); let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void()); - catch.call(catch_ty, catch_func, &[data, catch_data], None); - catch.ret(bx.const_i32(1)); + bx.call(catch_ty, catch_func, &[data, catch_data], None); + bx.ret(bx.const_i32(1)); }); // Note that no invoke is used here because by definition this function diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index 13d9a47b106..ceb3d5a84ab 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -131,51 +131,47 @@ fn emit_aapcs_va_arg<'ll, 'tcx>( // it could be on the stack so we have to update the offset and then check // the offset again. - let mut maybe_reg = Builder::build(bx.cx, maybe_reg); + bx.switch_to_block(maybe_reg); if gr_type && layout.align.abi.bytes() > 8 { - reg_off_v = maybe_reg.add(reg_off_v, bx.const_i32(15)); - reg_off_v = maybe_reg.and(reg_off_v, bx.const_i32(-16)); + reg_off_v = bx.add(reg_off_v, bx.const_i32(15)); + reg_off_v = bx.and(reg_off_v, bx.const_i32(-16)); } - let new_reg_off_v = maybe_reg.add(reg_off_v, bx.const_i32(slot_size as i32)); + let new_reg_off_v = bx.add(reg_off_v, bx.const_i32(slot_size as i32)); - maybe_reg.store(new_reg_off_v, reg_off, offset_align); + bx.store(new_reg_off_v, reg_off, offset_align); // Check to see if we have overflowed the registers as a result of this. // If we have then we need to use the stack for this value - let use_stack = maybe_reg.icmp(IntPredicate::IntSGT, new_reg_off_v, zero); - maybe_reg.cond_br(use_stack, on_stack, in_reg); + let use_stack = bx.icmp(IntPredicate::IntSGT, new_reg_off_v, zero); + bx.cond_br(use_stack, on_stack, in_reg); - let mut in_reg = Builder::build(bx.cx, in_reg); + bx.switch_to_block(in_reg); let top_type = bx.type_i8p(); - let top = in_reg.struct_gep(va_list_ty, va_list_addr, reg_top_index); - let top = in_reg.load(top_type, top, bx.tcx().data_layout.pointer_align.abi); + let top = bx.struct_gep(va_list_ty, va_list_addr, reg_top_index); + let top = bx.load(top_type, top, bx.tcx().data_layout.pointer_align.abi); // reg_value = *(@top + reg_off_v); - let mut reg_addr = in_reg.gep(bx.type_i8(), top, &[reg_off_v]); + let mut reg_addr = bx.gep(bx.type_i8(), top, &[reg_off_v]); if bx.tcx().sess.target.endian == Endian::Big && layout.size.bytes() != slot_size { // On big-endian systems the value is right-aligned in its slot. let offset = bx.const_i32((slot_size - layout.size.bytes()) as i32); - reg_addr = in_reg.gep(bx.type_i8(), reg_addr, &[offset]); + reg_addr = bx.gep(bx.type_i8(), reg_addr, &[offset]); } let reg_type = layout.llvm_type(bx); - let reg_addr = in_reg.bitcast(reg_addr, bx.cx.type_ptr_to(reg_type)); - let reg_value = in_reg.load(reg_type, reg_addr, layout.align.abi); - in_reg.br(end); + let reg_addr = bx.bitcast(reg_addr, bx.cx.type_ptr_to(reg_type)); + let reg_value = bx.load(reg_type, reg_addr, layout.align.abi); + bx.br(end); // On Stack block - let mut on_stack = Builder::build(bx.cx, on_stack); + bx.switch_to_block(on_stack); let stack_value = - emit_ptr_va_arg(&mut on_stack, list, target_ty, false, Align::from_bytes(8).unwrap(), true); - on_stack.br(end); + emit_ptr_va_arg(bx, list, target_ty, false, Align::from_bytes(8).unwrap(), true); + bx.br(end); - let mut end = Builder::build(bx.cx, end); - let val = end.phi( - layout.immediate_llvm_type(bx), - &[reg_value, stack_value], - &[in_reg.llbb(), on_stack.llbb()], - ); + bx.switch_to_block(end); + let val = + bx.phi(layout.immediate_llvm_type(bx), &[reg_value, stack_value], &[in_reg, on_stack]); - *bx = end; val } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index ca46d230b72..39375b95b19 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -170,10 +170,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } if let Some((ret_dest, target)) = destination { - let target_llbb = fx.llbb(target); - let mut ret_bx = Bx::build(fx.cx, target_llbb); - fx.set_debug_loc(&mut ret_bx, self.terminator.source_info); - fx.store_return(&mut ret_bx, ret_dest, &fn_abi.ret, invokeret); + bx.switch_to_block(fx.llbb(target)); + fx.set_debug_loc(bx, self.terminator.source_info); + fx.store_return(bx, ret_dest, &fn_abi.ret, invokeret); } } else { let llret = bx.call(fn_ty, fn_ptr, &llargs, self.funclet(fx)); @@ -462,7 +461,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } // After this point, bx is the block for the call to panic. - bx = Bx::build(self.cx, panic_block); + bx.switch_to_block(panic_block); self.set_debug_loc(&mut bx, terminator.source_info); // Get the location information. @@ -914,10 +913,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let bb_fail = bx.append_sibling_block("type_test.fail"); bx.cond_br(cond, bb_pass, bb_fail); - let mut bx_pass = Bx::build(self.cx, bb_pass); + bx.switch_to_block(bb_pass); helper.do_call( self, - &mut bx_pass, + &mut bx, fn_abi, fn_ptr, &llargs, @@ -925,9 +924,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cleanup, ); - let mut bx_fail = Bx::build(self.cx, bb_fail); - bx_fail.abort(); - bx_fail.unreachable(); + bx.switch_to_block(bb_fail); + bx.abort(); + bx.unreachable(); return; } diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 6c7162c68d4..1c7fe060ea4 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -53,6 +53,8 @@ pub trait BuilderMethods<'a, 'tcx>: fn append_sibling_block(&mut self, name: &str) -> Self::BasicBlock; + fn switch_to_block(&mut self, llbb: Self::BasicBlock); + fn ret_void(&mut self); fn ret(&mut self, v: Self::Value); fn br(&mut self, dest: Self::BasicBlock);