Skip to content

Commit 78e2ac0

Browse files
committed
rustc_codegen_ssa: turn builders "unpositioned" after emitting a terminator.
1 parent ce953ec commit 78e2ac0

File tree

6 files changed

+256
-233
lines changed

6 files changed

+256
-233
lines changed

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -161,58 +161,63 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
161161

162162
fn set_span(&mut self, _span: Span) {}
163163

164-
fn ret_void(&mut self) {
164+
fn ret_void(self) -> Self::Unpositioned {
165165
unsafe {
166166
llvm::LLVMBuildRetVoid(self.llbuilder);
167167
}
168+
self.into_unpositioned()
168169
}
169170

170-
fn ret(&mut self, v: &'ll Value) {
171+
fn ret(self, v: &'ll Value) -> Self::Unpositioned {
171172
unsafe {
172173
llvm::LLVMBuildRet(self.llbuilder, v);
173174
}
175+
self.into_unpositioned()
174176
}
175177

176-
fn br(&mut self, dest: &'ll BasicBlock) {
178+
fn br(self, dest: &'ll BasicBlock) -> Self::Unpositioned {
177179
unsafe {
178180
llvm::LLVMBuildBr(self.llbuilder, dest);
179181
}
182+
self.into_unpositioned()
180183
}
181184

182185
fn cond_br(
183-
&mut self,
186+
self,
184187
cond: &'ll Value,
185188
then_llbb: &'ll BasicBlock,
186189
else_llbb: &'ll BasicBlock,
187-
) {
190+
) -> Self::Unpositioned {
188191
unsafe {
189192
llvm::LLVMBuildCondBr(self.llbuilder, cond, then_llbb, else_llbb);
190193
}
194+
self.into_unpositioned()
191195
}
192196

193197
fn switch(
194-
&mut self,
198+
self,
195199
v: &'ll Value,
196200
else_llbb: &'ll BasicBlock,
197201
cases: impl ExactSizeIterator<Item = (u128, &'ll BasicBlock)>,
198-
) {
202+
) -> Self::Unpositioned {
199203
let switch =
200204
unsafe { llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, cases.len() as c_uint) };
201205
for (on_val, dest) in cases {
202206
let on_val = self.const_uint_big(self.val_ty(v), on_val);
203207
unsafe { llvm::LLVMAddCase(switch, on_val, dest) }
204208
}
209+
self.into_unpositioned()
205210
}
206211

207212
fn invoke(
208-
&mut self,
213+
mut self,
209214
llfn: &'ll Value,
210215
args: &[&'ll Value],
211216
then: &'ll BasicBlock,
212217
catch: &'ll BasicBlock,
213218
funclet: Option<&Funclet<'ll>>,
214219
fn_abi_for_attrs: Option<&FnAbi<'tcx, Ty<'tcx>>>,
215-
) -> &'ll Value {
220+
) -> (Self::Unpositioned, &'ll Value) {
216221
debug!("invoke {:?} with args ({:?})", llfn, args);
217222

218223
let args = self.check_call("invoke", llfn, args);
@@ -232,15 +237,16 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
232237
)
233238
};
234239
if let Some(fn_abi) = fn_abi_for_attrs {
235-
fn_abi.apply_attrs_callsite(self, invoke);
240+
fn_abi.apply_attrs_callsite(&mut self, invoke);
236241
}
237-
invoke
242+
(self.into_unpositioned(), invoke)
238243
}
239244

240-
fn unreachable(&mut self) {
245+
fn unreachable(self) -> Self::Unpositioned {
241246
unsafe {
242247
llvm::LLVMBuildUnreachable(self.llbuilder);
243248
}
249+
self.into_unpositioned()
244250
}
245251

246252
builder_methods_for_value_instructions! {
@@ -530,29 +536,33 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
530536
count: u64,
531537
dest: PlaceRef<'tcx, &'ll Value>,
532538
) -> Self {
533-
let zero = self.const_usize(0);
534-
let count = self.const_usize(count);
535-
let start = dest.project_index(&mut self, zero).llval;
536-
let end = dest.project_index(&mut self, count).llval;
539+
let cx = self.cx;
540+
let original_llbb = self.llbb();
541+
542+
let start = dest.project_index(&mut self, cx.const_usize(0)).llval;
543+
let end = dest.project_index(&mut self, cx.const_usize(count)).llval;
537544

538545
let mut header_bx = self.build_sibling_block("repeat_loop_header");
546+
let header_llbb = header_bx.llbb();
539547
let mut body_bx = self.build_sibling_block("repeat_loop_body");
548+
let body_llbb = body_bx.llbb();
540549
let next_bx = self.build_sibling_block("repeat_loop_next");
541550

551+
let current_llty = cx.val_ty(start);
542552
self.br(header_bx.llbb());
543-
let current = header_bx.phi(self.val_ty(start), &[start], &[self.llbb()]);
553+
let current = header_bx.phi(current_llty, &[start], &[original_llbb]);
544554

545555
let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
546556
header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
547557

548-
let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size);
558+
let align = dest.align.restrict_for_offset(dest.layout.field(cx, 0).size);
549559
cg_elem
550560
.val
551561
.store(&mut body_bx, PlaceRef::new_sized_aligned(current, cg_elem.layout, align));
552562

553-
let next = body_bx.inbounds_gep(current, &[self.const_usize(1)]);
554-
body_bx.br(header_bx.llbb());
555-
Self::add_incoming_to_phi(current, &[next], &[body_bx.llbb()]);
563+
let next = body_bx.inbounds_gep(current, &[cx.const_usize(1)]);
564+
body_bx.br(header_llbb);
565+
Self::add_incoming_to_phi(current, &[next], &[body_llbb]);
556566

557567
next_bx
558568
}
@@ -958,8 +968,9 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
958968
}
959969
}
960970

961-
fn resume(&mut self, exn: &'ll Value) -> &'ll Value {
962-
unsafe { llvm::LLVMBuildResume(self.llbuilder, exn) }
971+
fn resume(self, exn: &'ll Value) -> (Self::Unpositioned, &'ll Value) {
972+
let resume = unsafe { llvm::LLVMBuildResume(self.llbuilder, exn) };
973+
(self.into_unpositioned(), resume)
963974
}
964975

965976
fn cleanup_pad(&mut self, parent: Option<&'ll Value>, args: &[&'ll Value]) -> Funclet<'ll> {
@@ -977,13 +988,13 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
977988
}
978989

979990
fn cleanup_ret(
980-
&mut self,
991+
self,
981992
funclet: &Funclet<'ll>,
982993
unwind: Option<&'ll BasicBlock>,
983-
) -> &'ll Value {
994+
) -> (Self::Unpositioned, &'ll Value) {
984995
let ret =
985996
unsafe { llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind) };
986-
ret.expect("LLVM does not have support for cleanupret")
997+
(self.into_unpositioned(), ret.expect("LLVM does not have support for cleanupret"))
987998
}
988999

9891000
fn catch_pad(&mut self, parent: &'ll Value, args: &[&'ll Value]) -> Funclet<'ll> {
@@ -1001,11 +1012,11 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
10011012
}
10021013

10031014
fn catch_switch(
1004-
&mut self,
1015+
self,
10051016
parent: Option<&'ll Value>,
10061017
unwind: Option<&'ll BasicBlock>,
10071018
handlers: &[&'ll BasicBlock],
1008-
) -> &'ll Value {
1019+
) -> (Self::Unpositioned, &'ll Value) {
10091020
let name = cstr!("catchswitch");
10101021
let ret = unsafe {
10111022
llvm::LLVMRustBuildCatchSwitch(
@@ -1022,7 +1033,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
10221033
llvm::LLVMRustAddHandler(catch_switch, handler);
10231034
}
10241035
}
1025-
catch_switch
1036+
(self.into_unpositioned(), catch_switch)
10261037
}
10271038

10281039
fn set_personality_fn(&mut self, personality: &'ll Value) {

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -405,13 +405,15 @@ fn codegen_msvc_try(
405405
dest: &'ll Value,
406406
) {
407407
let llfn = get_rust_try_fn(bx, &mut |mut bx| {
408+
let cx = bx.cx;
409+
408410
bx.set_personality_fn(bx.eh_personality());
409411

410-
let mut normal = bx.build_sibling_block("normal");
411-
let mut catchswitch = bx.build_sibling_block("catchswitch");
412+
let normal = bx.build_sibling_block("normal");
413+
let catchswitch = bx.build_sibling_block("catchswitch");
412414
let mut catchpad_rust = bx.build_sibling_block("catchpad_rust");
413415
let mut catchpad_foreign = bx.build_sibling_block("catchpad_foreign");
414-
let mut caught = bx.build_sibling_block("caught");
416+
let caught = bx.build_sibling_block("caught");
415417

416418
let try_func = llvm::get_param(bx.llfn(), 0);
417419
let data = llvm::get_param(bx.llfn(), 1);
@@ -476,9 +478,9 @@ fn codegen_msvc_try(
476478
let slot = bx.alloca(bx.type_i8p(), ptr_align);
477479
bx.invoke(try_func, &[data], normal.llbb(), catchswitch.llbb(), None, None);
478480

479-
normal.ret(bx.const_i32(0));
481+
normal.ret(cx.const_i32(0));
480482

481-
let cs =
483+
let (_, cs) =
482484
catchswitch.catch_switch(None, None, &[catchpad_rust.llbb(), catchpad_foreign.llbb()]);
483485

484486
// We can't use the TypeDescriptor defined in libpanic_unwind because it
@@ -495,14 +497,14 @@ fn codegen_msvc_try(
495497
//
496498
// When modifying, make sure that the type_name string exactly matches
497499
// the one used in src/libpanic_unwind/seh.rs.
498-
let type_info_vtable = bx.declare_global("??_7type_info@@6B@", bx.type_i8p());
499-
let type_name = bx.const_bytes(b"rust_panic\0");
500+
let type_info_vtable = cx.declare_global("??_7type_info@@6B@", cx.type_i8p());
501+
let type_name = cx.const_bytes(b"rust_panic\0");
500502
let type_info =
501-
bx.const_struct(&[type_info_vtable, bx.const_null(bx.type_i8p()), type_name], false);
502-
let tydesc = bx.declare_global("__rust_panic_type_info", bx.val_ty(type_info));
503+
cx.const_struct(&[type_info_vtable, cx.const_null(cx.type_i8p()), type_name], false);
504+
let tydesc = cx.declare_global("__rust_panic_type_info", cx.val_ty(type_info));
503505
unsafe {
504506
llvm::LLVMRustSetLinkage(tydesc, llvm::Linkage::LinkOnceODRLinkage);
505-
llvm::SetUniqueComdat(bx.llmod, tydesc);
507+
llvm::SetUniqueComdat(cx.llmod, tydesc);
506508
llvm::LLVMSetInitializer(tydesc, type_info);
507509
}
508510

@@ -512,20 +514,20 @@ fn codegen_msvc_try(
512514
// since our exception object effectively contains a Box.
513515
//
514516
// Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang
515-
let flags = bx.const_i32(8);
517+
let flags = cx.const_i32(8);
516518
let funclet = catchpad_rust.catch_pad(cs, &[tydesc, flags, slot]);
517519
let ptr = catchpad_rust.load(slot, ptr_align);
518520
catchpad_rust.call(catch_func, &[data, ptr], Some(&funclet), None);
519521
catchpad_rust.catch_ret(&funclet, caught.llbb());
520522

521523
// The flag value of 64 indicates a "catch-all".
522-
let flags = bx.const_i32(64);
523-
let null = bx.const_null(bx.type_i8p());
524+
let flags = cx.const_i32(64);
525+
let null = cx.const_null(cx.type_i8p());
524526
let funclet = catchpad_foreign.catch_pad(cs, &[null, flags, null]);
525527
catchpad_foreign.call(catch_func, &[data, null], Some(&funclet), None);
526528
catchpad_foreign.catch_ret(&funclet, caught.llbb());
527529

528-
caught.ret(bx.const_i32(1));
530+
caught.ret(cx.const_i32(1));
529531
});
530532

531533
// Note that no invoke is used here because by definition this function
@@ -553,7 +555,9 @@ fn codegen_gnu_try(
553555
catch_func: &'ll Value,
554556
dest: &'ll Value,
555557
) {
556-
let llfn = get_rust_try_fn(bx, &mut |mut bx| {
558+
let llfn = get_rust_try_fn(bx, &mut |bx| {
559+
let cx = bx.cx;
560+
557561
// Codegens the shims described above:
558562
//
559563
// bx:
@@ -566,28 +570,28 @@ fn codegen_gnu_try(
566570
// (%ptr, _) = landingpad
567571
// call %catch_func(%data, %ptr)
568572
// ret 1
569-
let mut then = bx.build_sibling_block("then");
573+
let then = bx.build_sibling_block("then");
570574
let mut catch = bx.build_sibling_block("catch");
571575

572576
let try_func = llvm::get_param(bx.llfn(), 0);
573577
let data = llvm::get_param(bx.llfn(), 1);
574578
let catch_func = llvm::get_param(bx.llfn(), 2);
575579
bx.invoke(try_func, &[data], then.llbb(), catch.llbb(), None, None);
576-
then.ret(bx.const_i32(0));
580+
then.ret(cx.const_i32(0));
577581

578582
// Type indicator for the exception being thrown.
579583
//
580584
// The first value in this tuple is a pointer to the exception object
581585
// being thrown. The second value is a "selector" indicating which of
582586
// the landing pad clauses the exception's type had been matched to.
583587
// rust_try ignores the selector.
584-
let lpad_ty = bx.type_struct(&[bx.type_i8p(), bx.type_i32()], false);
585-
let vals = catch.landing_pad(lpad_ty, bx.eh_personality(), 1);
586-
let tydesc = bx.const_null(bx.type_i8p());
588+
let lpad_ty = cx.type_struct(&[cx.type_i8p(), cx.type_i32()], false);
589+
let vals = catch.landing_pad(lpad_ty, cx.eh_personality(), 1);
590+
let tydesc = cx.const_null(cx.type_i8p());
587591
catch.add_clause(vals, tydesc);
588592
let ptr = catch.extract_value(vals, 0);
589593
catch.call(catch_func, &[data, ptr], None, None);
590-
catch.ret(bx.const_i32(1));
594+
catch.ret(cx.const_i32(1));
591595
});
592596

593597
// Note that no invoke is used here because by definition this function
@@ -607,7 +611,9 @@ fn codegen_emcc_try(
607611
catch_func: &'ll Value,
608612
dest: &'ll Value,
609613
) {
610-
let llfn = get_rust_try_fn(bx, &mut |mut bx| {
614+
let llfn = get_rust_try_fn(bx, &mut |bx| {
615+
let cx = bx.cx;
616+
611617
// Codegens the shims described above:
612618
//
613619
// bx:
@@ -625,48 +631,48 @@ fn codegen_emcc_try(
625631
// %catch_data[1] = %is_rust_panic
626632
// call %catch_func(%data, %catch_data)
627633
// ret 1
628-
let mut then = bx.build_sibling_block("then");
634+
let then = bx.build_sibling_block("then");
629635
let mut catch = bx.build_sibling_block("catch");
630636

631637
let try_func = llvm::get_param(bx.llfn(), 0);
632638
let data = llvm::get_param(bx.llfn(), 1);
633639
let catch_func = llvm::get_param(bx.llfn(), 2);
634640
bx.invoke(try_func, &[data], then.llbb(), catch.llbb(), None, None);
635-
then.ret(bx.const_i32(0));
641+
then.ret(cx.const_i32(0));
636642

637643
// Type indicator for the exception being thrown.
638644
//
639645
// The first value in this tuple is a pointer to the exception object
640646
// being thrown. The second value is a "selector" indicating which of
641647
// the landing pad clauses the exception's type had been matched to.
642-
let tydesc = bx.eh_catch_typeinfo();
643-
let lpad_ty = bx.type_struct(&[bx.type_i8p(), bx.type_i32()], false);
644-
let vals = catch.landing_pad(lpad_ty, bx.eh_personality(), 2);
648+
let tydesc = cx.eh_catch_typeinfo();
649+
let lpad_ty = cx.type_struct(&[cx.type_i8p(), cx.type_i32()], false);
650+
let vals = catch.landing_pad(lpad_ty, cx.eh_personality(), 2);
645651
catch.add_clause(vals, tydesc);
646-
catch.add_clause(vals, bx.const_null(bx.type_i8p()));
652+
catch.add_clause(vals, cx.const_null(cx.type_i8p()));
647653
let ptr = catch.extract_value(vals, 0);
648654
let selector = catch.extract_value(vals, 1);
649655

650656
// Check if the typeid we got is the one for a Rust panic.
651-
let llvm_eh_typeid_for = bx.get_intrinsic("llvm.eh.typeid.for");
657+
let llvm_eh_typeid_for = cx.get_intrinsic("llvm.eh.typeid.for");
652658
let rust_typeid = catch.call(llvm_eh_typeid_for, &[tydesc], None, None);
653659
let is_rust_panic = catch.icmp(IntPredicate::IntEQ, selector, rust_typeid);
654-
let is_rust_panic = catch.zext(is_rust_panic, bx.type_bool());
660+
let is_rust_panic = catch.zext(is_rust_panic, cx.type_bool());
655661

656662
// We need to pass two values to catch_func (ptr and is_rust_panic), so
657663
// create an alloca and pass a pointer to that.
658-
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
659-
let i8_align = bx.tcx().data_layout.i8_align.abi;
664+
let ptr_align = cx.tcx.data_layout.pointer_align.abi;
665+
let i8_align = cx.tcx.data_layout.i8_align.abi;
660666
let catch_data =
661-
catch.alloca(bx.type_struct(&[bx.type_i8p(), bx.type_bool()], false), ptr_align);
662-
let catch_data_0 = catch.inbounds_gep(catch_data, &[bx.const_usize(0), bx.const_usize(0)]);
667+
catch.alloca(cx.type_struct(&[cx.type_i8p(), cx.type_bool()], false), ptr_align);
668+
let catch_data_0 = catch.inbounds_gep(catch_data, &[cx.const_usize(0), cx.const_usize(0)]);
663669
catch.store(ptr, catch_data_0, ptr_align);
664-
let catch_data_1 = catch.inbounds_gep(catch_data, &[bx.const_usize(0), bx.const_usize(1)]);
670+
let catch_data_1 = catch.inbounds_gep(catch_data, &[cx.const_usize(0), cx.const_usize(1)]);
665671
catch.store(is_rust_panic, catch_data_1, i8_align);
666-
let catch_data = catch.bitcast(catch_data, bx.type_i8p());
672+
let catch_data = catch.bitcast(catch_data, cx.type_i8p());
667673

668674
catch.call(catch_func, &[data, catch_data], None, None);
669-
catch.ret(bx.const_i32(1));
675+
catch.ret(cx.const_i32(1));
670676
});
671677

672678
// Note that no invoke is used here because by definition this function

0 commit comments

Comments
 (0)