Skip to content

Commit 396baa7

Browse files
committed
Make allocator shim creation mostly use safe code
1 parent 840e31b commit 396baa7

File tree

5 files changed

+94
-96
lines changed

5 files changed

+94
-96
lines changed

compiler/rustc_codegen_llvm/src/allocator.rs

Lines changed: 70 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,31 @@ use rustc_ast::expand::allocator::{
33
ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
44
alloc_error_handler_name, default_fn_name, global_fn_name,
55
};
6+
use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _;
67
use rustc_middle::bug;
78
use rustc_middle::ty::TyCtxt;
89
use rustc_session::config::{DebugInfo, OomStrategy};
910

10-
use crate::common::AsCCharPtr;
11-
use crate::llvm::{self, Context, False, Module, True, Type};
12-
use crate::{ModuleLlvm, attributes, debuginfo};
11+
use crate::builder::SBuilder;
12+
use crate::declare::declare_simple_fn;
13+
use crate::llvm::{self, False, True, Type};
14+
use crate::{SimpleCx, attributes, debuginfo};
1315

1416
pub(crate) unsafe fn codegen(
1517
tcx: TyCtxt<'_>,
16-
module_llvm: &mut ModuleLlvm,
18+
cx: SimpleCx<'_>,
1719
module_name: &str,
1820
kind: AllocatorKind,
1921
alloc_error_handler_kind: AllocatorKind,
2022
) {
21-
let llcx = &*module_llvm.llcx;
22-
let llmod = module_llvm.llmod();
23-
let usize = unsafe {
24-
match tcx.sess.target.pointer_width {
25-
16 => llvm::LLVMInt16TypeInContext(llcx),
26-
32 => llvm::LLVMInt32TypeInContext(llcx),
27-
64 => llvm::LLVMInt64TypeInContext(llcx),
28-
tws => bug!("Unsupported target word size for int: {}", tws),
29-
}
23+
let usize = match tcx.sess.target.pointer_width {
24+
16 => cx.type_i16(),
25+
32 => cx.type_i32(),
26+
64 => cx.type_i64(),
27+
tws => bug!("Unsupported target word size for int: {}", tws),
3028
};
31-
let i8 = unsafe { llvm::LLVMInt8TypeInContext(llcx) };
32-
let i8p = unsafe { llvm::LLVMPointerTypeInContext(llcx, 0) };
29+
let i8 = cx.type_i8();
30+
let i8p = cx.type_ptr();
3331

3432
if kind == AllocatorKind::Default {
3533
for method in ALLOCATOR_METHODS {
@@ -58,15 +56,14 @@ pub(crate) unsafe fn codegen(
5856
let from_name = global_fn_name(method.name);
5957
let to_name = default_fn_name(method.name);
6058

61-
create_wrapper_function(tcx, llcx, llmod, &from_name, &to_name, &args, output, false);
59+
create_wrapper_function(tcx, &cx, &from_name, &to_name, &args, output, false);
6260
}
6361
}
6462

6563
// rust alloc error handler
6664
create_wrapper_function(
6765
tcx,
68-
llcx,
69-
llmod,
66+
&cx,
7067
"__rust_alloc_error_handler",
7168
alloc_error_handler_name(alloc_error_handler_kind),
7269
&[usize, usize], // size, align
@@ -77,99 +74,86 @@ pub(crate) unsafe fn codegen(
7774
unsafe {
7875
// __rust_alloc_error_handler_should_panic
7976
let name = OomStrategy::SYMBOL;
80-
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_c_char_ptr(), name.len(), i8);
77+
let ll_g = cx.declare_global(name, i8);
8178
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
8279
let val = tcx.sess.opts.unstable_opts.oom.should_panic();
8380
let llval = llvm::LLVMConstInt(i8, val as u64, False);
8481
llvm::set_initializer(ll_g, llval);
8582

8683
let name = NO_ALLOC_SHIM_IS_UNSTABLE;
87-
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_c_char_ptr(), name.len(), i8);
84+
let ll_g = cx.declare_global(name, i8);
8885
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
8986
let llval = llvm::LLVMConstInt(i8, 0, False);
9087
llvm::set_initializer(ll_g, llval);
9188
}
9289

9390
if tcx.sess.opts.debuginfo != DebugInfo::None {
94-
let dbg_cx = debuginfo::CodegenUnitDebugContext::new(llmod);
91+
let dbg_cx = debuginfo::CodegenUnitDebugContext::new(cx.llmod);
9592
debuginfo::metadata::build_compile_unit_di_node(tcx, module_name, &dbg_cx);
9693
dbg_cx.finalize(tcx.sess);
9794
}
9895
}
9996

10097
fn create_wrapper_function(
10198
tcx: TyCtxt<'_>,
102-
llcx: &Context,
103-
llmod: &Module,
99+
cx: &SimpleCx<'_>,
104100
from_name: &str,
105101
to_name: &str,
106102
args: &[&Type],
107103
output: Option<&Type>,
108104
no_return: bool,
109105
) {
110-
unsafe {
111-
let ty = llvm::LLVMFunctionType(
112-
output.unwrap_or_else(|| llvm::LLVMVoidTypeInContext(llcx)),
113-
args.as_ptr(),
114-
args.len() as c_uint,
115-
False,
116-
);
117-
let llfn = llvm::LLVMRustGetOrInsertFunction(
118-
llmod,
119-
from_name.as_c_char_ptr(),
120-
from_name.len(),
121-
ty,
122-
);
123-
let no_return = if no_return {
124-
// -> ! DIFlagNoReturn
125-
let no_return = llvm::AttributeKind::NoReturn.create_attr(llcx);
126-
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[no_return]);
127-
Some(no_return)
128-
} else {
129-
None
130-
};
131-
132-
llvm::set_visibility(llfn, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
133-
134-
if tcx.sess.must_emit_unwind_tables() {
135-
let uwtable =
136-
attributes::uwtable_attr(llcx, tcx.sess.opts.unstable_opts.use_sync_unwind);
137-
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
138-
}
106+
let ty = cx.type_func(args, output.unwrap_or_else(|| cx.type_void()));
107+
let llfn = declare_simple_fn(
108+
&cx,
109+
from_name,
110+
llvm::CallConv::CCallConv,
111+
llvm::UnnamedAddr::Global,
112+
llvm::Visibility::from_generic(tcx.sess.default_visibility()),
113+
ty,
114+
);
115+
let no_return = if no_return {
116+
// -> ! DIFlagNoReturn
117+
let no_return = llvm::AttributeKind::NoReturn.create_attr(cx.llcx);
118+
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[no_return]);
119+
Some(no_return)
120+
} else {
121+
None
122+
};
139123

140-
let callee =
141-
llvm::LLVMRustGetOrInsertFunction(llmod, to_name.as_c_char_ptr(), to_name.len(), ty);
142-
if let Some(no_return) = no_return {
143-
// -> ! DIFlagNoReturn
144-
attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]);
145-
}
146-
llvm::set_visibility(callee, llvm::Visibility::Hidden);
147-
148-
let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, c"entry".as_ptr());
149-
150-
let llbuilder = llvm::LLVMCreateBuilderInContext(llcx);
151-
llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb);
152-
let args = args
153-
.iter()
154-
.enumerate()
155-
.map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
156-
.collect::<Vec<_>>();
157-
let ret = llvm::LLVMBuildCallWithOperandBundles(
158-
llbuilder,
159-
ty,
160-
callee,
161-
args.as_ptr(),
162-
args.len() as c_uint,
163-
[].as_ptr(),
164-
0 as c_uint,
165-
c"".as_ptr(),
166-
);
167-
llvm::LLVMSetTailCall(ret, True);
168-
if output.is_some() {
169-
llvm::LLVMBuildRet(llbuilder, ret);
170-
} else {
171-
llvm::LLVMBuildRetVoid(llbuilder);
172-
}
173-
llvm::LLVMDisposeBuilder(llbuilder);
124+
if tcx.sess.must_emit_unwind_tables() {
125+
let uwtable =
126+
attributes::uwtable_attr(cx.llcx, tcx.sess.opts.unstable_opts.use_sync_unwind);
127+
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
128+
}
129+
130+
let callee = declare_simple_fn(
131+
&cx,
132+
to_name,
133+
llvm::CallConv::CCallConv,
134+
llvm::UnnamedAddr::Global,
135+
llvm::Visibility::Hidden,
136+
ty,
137+
);
138+
if let Some(no_return) = no_return {
139+
// -> ! DIFlagNoReturn
140+
attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]);
141+
}
142+
llvm::set_visibility(callee, llvm::Visibility::Hidden);
143+
144+
let llbb = unsafe { llvm::LLVMAppendBasicBlockInContext(cx.llcx, llfn, c"entry".as_ptr()) };
145+
146+
let mut bx = SBuilder::build(&cx, llbb);
147+
let args = args
148+
.iter()
149+
.enumerate()
150+
.map(|(i, _)| llvm::get_param(llfn, i as c_uint))
151+
.collect::<Vec<_>>();
152+
let ret = bx.call(ty, callee, &args, None);
153+
llvm::LLVMSetTailCall(ret, True);
154+
if output.is_some() {
155+
bx.ret(ret);
156+
} else {
157+
bx.ret_void()
174158
}
175159
}

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> Drop for GenericBuilder<'a, 'll, CX> {
5757
}
5858

5959
impl<'a, 'll> SBuilder<'a, 'll> {
60-
fn call(
60+
pub(crate) fn call(
6161
&mut self,
6262
llty: &'ll Type,
6363
llfn: &'ll Value,
@@ -100,17 +100,17 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
100100
unsafe { llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, UNNAMED) }
101101
}
102102

103-
fn ret_void(&mut self) {
103+
pub(crate) fn ret_void(&mut self) {
104104
llvm::LLVMBuildRetVoid(self.llbuilder);
105105
}
106106

107-
fn ret(&mut self, v: &'ll Value) {
107+
pub(crate) fn ret(&mut self, v: &'ll Value) {
108108
unsafe {
109109
llvm::LLVMBuildRet(self.llbuilder, v);
110110
}
111111
}
112112

113-
fn build(cx: &'a GenericCx<'ll, CX>, llbb: &'ll BasicBlock) -> Self {
113+
pub(crate) fn build(cx: &'a GenericCx<'ll, CX>, llbb: &'ll BasicBlock) -> Self {
114114
let bx = Self::with_cx(cx);
115115
unsafe {
116116
llvm::LLVMPositionBuilderAtEnd(bx.llbuilder, llbb);

compiler/rustc_codegen_llvm/src/declare.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
//! * Use define_* family of methods when you might be defining the Value.
1212
//! * When in doubt, define.
1313
14+
use std::borrow::Borrow;
15+
1416
use itertools::Itertools;
1517
use rustc_codegen_ssa::traits::TypeMembershipCodegenMethods;
1618
use rustc_data_structures::fx::FxIndexSet;
@@ -22,7 +24,7 @@ use tracing::debug;
2224

2325
use crate::abi::FnAbiLlvmExt;
2426
use crate::common::AsCCharPtr;
25-
use crate::context::{CodegenCx, SimpleCx};
27+
use crate::context::{CodegenCx, GenericCx, SCx, SimpleCx};
2628
use crate::llvm::AttributePlace::Function;
2729
use crate::llvm::Visibility;
2830
use crate::type_::Type;
@@ -81,16 +83,25 @@ pub(crate) fn declare_raw_fn<'ll, 'tcx>(
8183
llfn
8284
}
8385

84-
impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
86+
impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
8587
/// Declare a global value.
8688
///
8789
/// If there’s a value with the same name already declared, the function will
8890
/// return its Value instead.
8991
pub(crate) fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value {
9092
debug!("declare_global(name={:?})", name);
91-
unsafe { llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_c_char_ptr(), name.len(), ty) }
93+
unsafe {
94+
llvm::LLVMRustGetOrInsertGlobal(
95+
(**self).borrow().llmod,
96+
name.as_c_char_ptr(),
97+
name.len(),
98+
ty,
99+
)
100+
}
92101
}
102+
}
93103

104+
impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
94105
/// Declare a C ABI function.
95106
///
96107
/// Only use this for foreign function ABIs and glue. For Rust functions use

compiler/rustc_codegen_llvm/src/lib.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use std::mem::ManuallyDrop;
2929

3030
use back::owned_target_machine::OwnedTargetMachine;
3131
use back::write::{create_informational_target_machine, create_target_machine};
32+
use context::SimpleCx;
3233
use errors::{AutoDiffWithoutLTO, ParseTargetMachineConfig};
3334
pub(crate) use llvm_util::target_features_cfg;
3435
use rustc_ast::expand::allocator::AllocatorKind;
@@ -116,9 +117,11 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
116117
kind: AllocatorKind,
117118
alloc_error_handler_kind: AllocatorKind,
118119
) -> ModuleLlvm {
119-
let mut module_llvm = ModuleLlvm::new_metadata(tcx, module_name);
120+
let module_llvm = ModuleLlvm::new_metadata(tcx, module_name);
121+
let cx =
122+
SimpleCx::new(module_llvm.llmod(), &module_llvm.llcx, tcx.data_layout.pointer_size);
120123
unsafe {
121-
allocator::codegen(tcx, &mut module_llvm, module_name, kind, alloc_error_handler_kind);
124+
allocator::codegen(tcx, cx, module_name, kind, alloc_error_handler_kind);
122125
}
123126
module_llvm
124127
}

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1147,7 +1147,7 @@ unsafe extern "C" {
11471147
pub(crate) fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode);
11481148
pub(crate) fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
11491149
pub(crate) fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
1150-
pub(crate) fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
1150+
pub(crate) safe fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
11511151

11521152
// Operations on attributes
11531153
pub(crate) fn LLVMCreateStringAttribute(

0 commit comments

Comments
 (0)