Skip to content

Partially move cg_ssa towards using a single builder #94123

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 19 additions & 16 deletions compiler/rustc_codegen_gcc/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand All @@ -409,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)
}
Expand Down Expand Up @@ -880,28 +880,31 @@ 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 keep_going = header_bx.icmp(IntPredicate::IntNE, current_val, end);
header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
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);

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_bx.llbb());
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);

next_bx
self.switch_to_block(next_bb);
self
}

fn range_metadata(&mut self, _load: RValue<'gcc>, _range: WrappingRange) {
Expand Down
24 changes: 13 additions & 11 deletions compiler/rustc_codegen_llvm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,8 @@ 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 switch_to_block(&mut self, llbb: Self::BasicBlock) {
*self = Self::build(self.cx, llbb)
}

fn ret_void(&mut self) {
Expand Down Expand Up @@ -544,16 +543,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
Expand All @@ -564,10 +566,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) {
Expand Down
112 changes: 58 additions & 54 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);

normal.ret(bx.const_i32(0));
bx.switch_to_block(normal);
bx.ret(bx.const_i32(0));

let cs =
catchswitch.catch_switch(None, None, &[catchpad_rust.llbb(), catchpad_foreign.llbb()]);
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
Expand Down Expand Up @@ -558,21 +559,24 @@ fn codegen_msvc_try<'ll>(
// since our exception object effectively contains a Box.
//
// Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang
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.llbb());
bx.call(catch_ty, catch_func, &[data, ptr], Some(&funclet));
bx.catch_ret(&funclet, caught);

// The flag value of 64 indicates a "catch-all".
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.llbb());
let funclet = bx.catch_pad(cs, &[null, flags, null]);
bx.call(catch_ty, catch_func, &[data, null], Some(&funclet));
bx.catch_ret(&funclet, 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
Expand Down Expand Up @@ -613,30 +617,33 @@ 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);
then.ret(bx.const_i32(0));
bx.invoke(try_func_ty, try_func, &[data], then, catch, None);

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.
// rust_try ignores the selector.
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
Expand Down Expand Up @@ -674,57 +681,54 @@ 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);
then.ret(bx.const_i32(0));
bx.invoke(try_func_ty, try_func, &[data], then, catch, None);

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.
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
Expand Down
Loading