From 402e9efc56fb21464a0cddf9aeab57c7512cf71d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 6 May 2021 17:37:19 +0300 Subject: [PATCH 1/2] rustc_codegen_ssa: only create backend `BasicBlock`s as-needed. --- compiler/rustc_codegen_llvm/src/builder.rs | 4 -- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 - compiler/rustc_codegen_ssa/src/mir/block.rs | 28 +++++++--- compiler/rustc_codegen_ssa/src/mir/mod.rs | 52 +++++++------------ .../rustc_codegen_ssa/src/traits/builder.rs | 1 - src/test/codegen/drop.rs | 9 ++-- src/test/codegen/match.rs | 6 +-- 7 files changed, 50 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 053cda1e7cc9c..c4efd9dbdbc2a 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1148,10 +1148,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { self.cx } - unsafe fn delete_basic_block(&mut self, bb: &'ll BasicBlock) { - llvm::LLVMDeleteBasicBlock(bb); - } - fn do_not_inline(&mut self, llret: &'ll Value) { llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 32fdde9b42e5f..bf66040a7ebad 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1079,7 +1079,6 @@ extern "C" { Fn: &'a Value, Name: *const c_char, ) -> &'a BasicBlock; - pub fn LLVMDeleteBasicBlock(BB: &BasicBlock); // Operations on instructions pub fn LLVMIsAInstruction(Val: &Value) -> Option<&Value>; diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 8f92d3e6b804f..b26c7c9d51a1c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -68,7 +68,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { target: mir::BasicBlock, ) -> (Bx::BasicBlock, bool) { let span = self.terminator.source_info.span; - let lltarget = fx.blocks[target]; + let lltarget = fx.llbb(target); let target_funclet = fx.cleanup_kinds[target].funclet_bb(target); match (self.funclet_bb, target_funclet) { (None, None) => (lltarget, false), @@ -133,13 +133,13 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { // If there is a cleanup block and the function we're calling can unwind, then // do an invoke, otherwise do a call. if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) { - let ret_bx = if let Some((_, target)) = destination { - fx.blocks[target] + let ret_llbb = if let Some((_, target)) = destination { + fx.llbb(target) } else { fx.unreachable_block() }; let invokeret = - bx.invoke(fn_ptr, &llargs, ret_bx, self.llblock(fx, cleanup), self.funclet(fx)); + bx.invoke(fn_ptr, &llargs, ret_llbb, self.llblock(fx, cleanup), self.funclet(fx)); bx.apply_attrs_callsite(&fn_abi, invokeret); if let Some((ret_dest, target)) = destination { @@ -1205,7 +1205,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // FIXME(eddyb) rename this to `eh_pad_for_uncached`. fn landing_pad_for_uncached(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock { - let llbb = self.blocks[bb]; + let llbb = self.llbb(bb); if base::wants_msvc_seh(self.cx.sess()) { let funclet; let ret_llbb; @@ -1293,9 +1293,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { Bx::new_block(self.cx, self.llfn, name) } - pub fn build_block(&self, bb: mir::BasicBlock) -> Bx { + /// 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 + // more backend-agnostic prefix such as `cg` (i.e. this would be `cgbb`). + pub fn llbb(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock { + self.cached_llbbs[bb].unwrap_or_else(|| { + // FIXME(eddyb) only name the block if `fewer_names` is `false`. + // FIXME(eddyb) create the block directly, without a builder. + let llbb = self.new_block(&format!("{:?}", bb)).llbb(); + self.cached_llbbs[bb] = Some(llbb); + llbb + }) + } + + pub fn build_block(&mut self, bb: mir::BasicBlock) -> Bx { let mut bx = Bx::with_cx(self.cx); - bx.position_at_end(self.blocks[bb]); + bx.position_at_end(self.llbb(bb)); bx } diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index a14ae16517db0..73d08b84cb898 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -40,8 +40,11 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { /// then later loaded when generating the DIVERGE_BLOCK. personality_slot: Option>, - /// A `Block` for each MIR `BasicBlock` - blocks: IndexVec, + /// A backend `BasicBlock` for each MIR `BasicBlock`, created lazily + /// as-needed (e.g. RPO reaching it or another block branching to it). + // FIXME(eddyb) rename `llbbs` and other `ll`-prefixed things to use a + // more backend-agnostic prefix such as `cg` (i.e. this would be `cgbbs`). + cached_llbbs: IndexVec>, /// The funclet status of each basic block cleanup_kinds: IndexVec, @@ -151,17 +154,17 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Allocate a `Block` for every basic block, except // the start block, if nothing loops back to it. let reentrant_start_block = !mir.predecessors()[mir::START_BLOCK].is_empty(); - let block_bxs: IndexVec = mir - .basic_blocks() - .indices() - .map(|bb| { - if bb == mir::START_BLOCK && !reentrant_start_block { - bx.llbb() - } else { - bx.build_sibling_block(&format!("{:?}", bb)).llbb() - } - }) - .collect(); + let cached_llbbs: IndexVec> = + mir.basic_blocks() + .indices() + .map(|bb| { + if bb == mir::START_BLOCK && !reentrant_start_block { + Some(bx.llbb()) + } else { + None + } + }) + .collect(); let mut fx = FunctionCx { instance, @@ -170,7 +173,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fn_abi, cx, personality_slot: None, - blocks: block_bxs, + cached_llbbs, unreachable_block: None, cleanup_kinds, landing_pads: IndexVec::from_elem(None, mir.basic_blocks()), @@ -245,29 +248,14 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Branch to the START block, if it's not the entry block. if reentrant_start_block { - bx.br(fx.blocks[mir::START_BLOCK]); + bx.br(fx.llbb(mir::START_BLOCK)); } - let rpo = traversal::reverse_postorder(&mir); - let mut visited = BitSet::new_empty(mir.basic_blocks().len()); - // Codegen the body of each block using reverse postorder - for (bb, _) in rpo { - visited.insert(bb.index()); + // FIXME(eddyb) reuse RPO iterator between `analysis` and this. + for (bb, _) in traversal::reverse_postorder(&mir) { fx.codegen_block(bb); } - - // Remove blocks that haven't been visited, or have no - // predecessors. - for bb in mir.basic_blocks().indices() { - // Unreachable block - if !visited.contains(bb.index()) { - debug!("codegen_mir: block {:?} was not visited", bb); - unsafe { - bx.delete_basic_block(fx.blocks[bb]); - } - } - } } /// Produces, for each argument, a `Value` pointing at the diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 1bc05f30e5c37..1c1aa1c5c888d 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -291,6 +291,5 @@ pub trait BuilderMethods<'a, 'tcx>: ) -> Self::Value; fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; - unsafe fn delete_basic_block(&mut self, bb: Self::BasicBlock); fn do_not_inline(&mut self, llret: Self::Value); } diff --git a/src/test/codegen/drop.rs b/src/test/codegen/drop.rs index b35d5c83552f2..543b81b0b6246 100644 --- a/src/test/codegen/drop.rs +++ b/src/test/codegen/drop.rs @@ -23,13 +23,16 @@ pub fn droppy() { // FIXME(eddyb) the `void @` forces a match on the instruction, instead of the // comment, that's `; call core::ptr::drop_in_place::` // for the `v0` mangling, should switch to matching on that once `legacy` is gone. -// CHECK-NOT: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName -// CHECK: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName -// CHECK: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName // CHECK-NOT: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName // CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName // CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName +// CHECK-NOT: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName +// CHECK: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName +// CHECK-NOT: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName // CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName +// CHECK-NOT: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName +// CHECK: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName +// CHECK-NOT: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName // CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName // CHECK-NOT: {{(call|invoke) void @.*}}drop_in_place{{.*}}SomeUniqueName // The next line checks for the } that ends the function definition diff --git a/src/test/codegen/match.rs b/src/test/codegen/match.rs index b5ee5ba2394d9..d0c0202052ed6 100644 --- a/src/test/codegen/match.rs +++ b/src/test/codegen/match.rs @@ -14,13 +14,13 @@ pub fn exhaustive_match(e: E) -> u8 { // CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[A:[a-zA-Z0-9_]+]] // CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[B:[a-zA-Z0-9_]+]] // CHECK-NEXT: ] -// CHECK: [[B]]: -// CHECK-NEXT: store i8 1, i8* %1, align 1 -// CHECK-NEXT: br label %[[EXIT:[a-zA-Z0-9_]+]] // CHECK: [[OTHERWISE]]: // CHECK-NEXT: unreachable // CHECK: [[A]]: // CHECK-NEXT: store i8 0, i8* %1, align 1 +// CHECK-NEXT: br label %[[EXIT:[a-zA-Z0-9_]+]] +// CHECK: [[B]]: +// CHECK-NEXT: store i8 1, i8* %1, align 1 // CHECK-NEXT: br label %[[EXIT:[a-zA-Z0-9_]+]] match e { E::A => 0, From 0fcaf11455b2864ba642216d4860c213b09a8db1 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 6 May 2021 18:57:04 +0300 Subject: [PATCH 2/2] rustc_codegen_ssa: append blocks to functions w/o creating a builder. --- compiler/rustc_codegen_llvm/src/builder.rs | 46 ++++++++++--------- .../src/coverageinfo/mod.rs | 3 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 3 +- compiler/rustc_codegen_ssa/src/base.rs | 3 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 17 +++---- compiler/rustc_codegen_ssa/src/mir/mod.rs | 5 +- .../rustc_codegen_ssa/src/traits/builder.rs | 15 ++++-- 7 files changed, 54 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index c4efd9dbdbc2a..bc9d99ed4a122 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -118,24 +118,16 @@ macro_rules! builder_methods_for_value_instructions { } impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { - fn new_block<'b>(cx: &'a CodegenCx<'ll, 'tcx>, llfn: &'ll Value, name: &'b str) -> Self { - let mut bx = Builder::with_cx(cx); - let llbb = unsafe { - let name = SmallCStr::new(name); - llvm::LLVMAppendBasicBlockInContext(cx.llcx, llfn, name.as_ptr()) - }; - bx.position_at_end(llbb); + fn build(cx: &'a CodegenCx<'ll, 'tcx>, llbb: &'ll BasicBlock) -> Self { + let bx = Builder::with_cx(cx); + unsafe { + llvm::LLVMPositionBuilderAtEnd(bx.llbuilder, llbb); + } bx } - fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self { - // Create a fresh builder from the crate context. - let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(cx.llcx) }; - Builder { llbuilder, cx } - } - - fn build_sibling_block(&self, name: &str) -> Self { - Builder::new_block(self.cx, self.llfn(), name) + fn cx(&self) -> &CodegenCx<'ll, 'tcx> { + self.cx } fn llbb(&self) -> &'ll BasicBlock { @@ -144,12 +136,22 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn set_span(&mut self, _span: Span) {} - fn position_at_end(&mut self, llbb: &'ll BasicBlock) { + fn append_block(cx: &'a CodegenCx<'ll, 'tcx>, llfn: &'ll Value, name: &str) -> &'ll BasicBlock { unsafe { - llvm::LLVMPositionBuilderAtEnd(self.llbuilder, llbb); + let name = SmallCStr::new(name); + llvm::LLVMAppendBasicBlockInContext(cx.llcx, llfn, name.as_ptr()) } } + fn append_sibling_block(&mut self, name: &str) -> &'ll BasicBlock { + 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); @@ -1144,10 +1146,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { unsafe { llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, UNNAMED) } } - fn cx(&self) -> &CodegenCx<'ll, 'tcx> { - self.cx - } - fn do_not_inline(&mut self, llret: &'ll Value) { llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret); } @@ -1161,6 +1159,12 @@ impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> { } impl Builder<'a, 'll, 'tcx> { + fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self { + // Create a fresh builder from the crate context. + let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(cx.llcx) }; + Builder { llbuilder, cx } + } + pub fn llfn(&self) -> &'ll Value { unsafe { llvm::LLVMGetBasicBlockParent(self.llbb()) } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index afc2bdbfd52ec..019bf4a09a787 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -223,7 +223,8 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx fn codegen_unused_fn_and_counter(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) { let llfn = cx.get_fn(instance); - let mut bx = Builder::new_block(cx, llfn, "unused_function"); + let llbb = Builder::append_block(cx, llfn, "unused_function"); + let mut bx = Builder::build(cx, llbb); let fn_name = bx.get_pgo_func_name_var(instance); let hash = bx.const_u64(0); let num_counters = bx.const_u32(1); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index fc6c1abf4af56..22d513d66d1cc 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -678,7 +678,8 @@ fn gen_fn<'ll, 'tcx>( cx.apply_target_cpu_attr(llfn); // FIXME(eddyb) find a nicer way to do this. unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; - let bx = Builder::new_block(cx, llfn, "entry-block"); + let llbb = Builder::append_block(cx, llfn, "entry-block"); + let bx = Builder::build(cx, llbb); codegen(bx); llfn } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index a9ab075d3db53..ac6a1a90bfd06 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -409,7 +409,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx.set_frame_pointer_elimination(llfn); cx.apply_target_cpu_attr(llfn); - let mut bx = Bx::new_block(&cx, llfn, "top"); + let llbb = Bx::append_block(&cx, llfn, "top"); + let mut bx = Bx::build(&cx, llbb); bx.insert_reference_to_gdb_debug_scripts_section_global(); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index b26c7c9d51a1c..93200bd1f264a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -386,7 +386,7 @@ 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 = self.new_block("panic"); + let panic_block = bx.build_sibling_block("panic"); if expected { bx.cond_br(cond, lltarget, panic_block.llbb()); } else { @@ -1289,8 +1289,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }) } - pub fn new_block(&self, name: &str) -> Bx { - Bx::new_block(self.cx, self.llfn, name) + // FIXME(eddyb) replace with `build_sibling_block`/`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 @@ -1300,17 +1303,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn llbb(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock { self.cached_llbbs[bb].unwrap_or_else(|| { // FIXME(eddyb) only name the block if `fewer_names` is `false`. - // FIXME(eddyb) create the block directly, without a builder. - let llbb = self.new_block(&format!("{:?}", bb)).llbb(); + let llbb = Bx::append_block(self.cx, self.llfn, &format!("{:?}", bb)); self.cached_llbbs[bb] = Some(llbb); llbb }) } pub fn build_block(&mut self, bb: mir::BasicBlock) -> Bx { - let mut bx = Bx::with_cx(self.cx); - bx.position_at_end(self.llbb(bb)); - bx + let llbb = self.llbb(bb); + Bx::build(self.cx, llbb) } fn make_return_dest( diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 73d08b84cb898..3bbc481b61093 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -144,7 +144,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir); - let mut bx = Bx::new_block(cx, llfn, "start"); + let start_llbb = Bx::append_block(cx, llfn, "start"); + let mut bx = Bx::build(cx, start_llbb); if mir.basic_blocks().iter().any(|bb| bb.is_cleanup) { bx.set_personality_fn(cx.eh_personality()); @@ -159,7 +160,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( .indices() .map(|bb| { if bb == mir::START_BLOCK && !reentrant_start_block { - Some(bx.llbb()) + Some(start_llbb) } else { None } diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 1c1aa1c5c888d..29b2db5d4d7af 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -40,14 +40,21 @@ pub trait BuilderMethods<'a, 'tcx>: + HasParamEnv<'tcx> + HasTargetSpec { - fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::Function, name: &'b str) -> Self; - fn with_cx(cx: &'a Self::CodegenCx) -> Self; - fn build_sibling_block(&self, name: &str) -> Self; + fn build(cx: &'a Self::CodegenCx, llbb: Self::BasicBlock) -> Self; + fn cx(&self) -> &Self::CodegenCx; fn llbb(&self) -> Self::BasicBlock; + fn set_span(&mut self, span: Span); - fn position_at_end(&mut self, llbb: Self::BasicBlock); + // FIXME(eddyb) replace uses of this with `append_sibling_block`. + fn append_block(cx: &'a Self::CodegenCx, llfn: Self::Function, name: &str) -> Self::BasicBlock; + + 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);