Make allocator shim creation mostly use safe code
This commit is contained in:
parent
840e31b29f
commit
396baa750e
5 changed files with 91 additions and 93 deletions
|
@ -3,33 +3,31 @@ use rustc_ast::expand::allocator::{
|
||||||
ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
|
ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
|
||||||
alloc_error_handler_name, default_fn_name, global_fn_name,
|
alloc_error_handler_name, default_fn_name, global_fn_name,
|
||||||
};
|
};
|
||||||
|
use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::config::{DebugInfo, OomStrategy};
|
use rustc_session::config::{DebugInfo, OomStrategy};
|
||||||
|
|
||||||
use crate::common::AsCCharPtr;
|
use crate::builder::SBuilder;
|
||||||
use crate::llvm::{self, Context, False, Module, True, Type};
|
use crate::declare::declare_simple_fn;
|
||||||
use crate::{ModuleLlvm, attributes, debuginfo};
|
use crate::llvm::{self, False, True, Type};
|
||||||
|
use crate::{SimpleCx, attributes, debuginfo};
|
||||||
|
|
||||||
pub(crate) unsafe fn codegen(
|
pub(crate) unsafe fn codegen(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
module_llvm: &mut ModuleLlvm,
|
cx: SimpleCx<'_>,
|
||||||
module_name: &str,
|
module_name: &str,
|
||||||
kind: AllocatorKind,
|
kind: AllocatorKind,
|
||||||
alloc_error_handler_kind: AllocatorKind,
|
alloc_error_handler_kind: AllocatorKind,
|
||||||
) {
|
) {
|
||||||
let llcx = &*module_llvm.llcx;
|
let usize = match tcx.sess.target.pointer_width {
|
||||||
let llmod = module_llvm.llmod();
|
16 => cx.type_i16(),
|
||||||
let usize = unsafe {
|
32 => cx.type_i32(),
|
||||||
match tcx.sess.target.pointer_width {
|
64 => cx.type_i64(),
|
||||||
16 => llvm::LLVMInt16TypeInContext(llcx),
|
tws => bug!("Unsupported target word size for int: {}", tws),
|
||||||
32 => llvm::LLVMInt32TypeInContext(llcx),
|
|
||||||
64 => llvm::LLVMInt64TypeInContext(llcx),
|
|
||||||
tws => bug!("Unsupported target word size for int: {}", tws),
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let i8 = unsafe { llvm::LLVMInt8TypeInContext(llcx) };
|
let i8 = cx.type_i8();
|
||||||
let i8p = unsafe { llvm::LLVMPointerTypeInContext(llcx, 0) };
|
let i8p = cx.type_ptr();
|
||||||
|
|
||||||
if kind == AllocatorKind::Default {
|
if kind == AllocatorKind::Default {
|
||||||
for method in ALLOCATOR_METHODS {
|
for method in ALLOCATOR_METHODS {
|
||||||
|
@ -58,15 +56,14 @@ pub(crate) unsafe fn codegen(
|
||||||
let from_name = global_fn_name(method.name);
|
let from_name = global_fn_name(method.name);
|
||||||
let to_name = default_fn_name(method.name);
|
let to_name = default_fn_name(method.name);
|
||||||
|
|
||||||
create_wrapper_function(tcx, llcx, llmod, &from_name, &to_name, &args, output, false);
|
create_wrapper_function(tcx, &cx, &from_name, &to_name, &args, output, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rust alloc error handler
|
// rust alloc error handler
|
||||||
create_wrapper_function(
|
create_wrapper_function(
|
||||||
tcx,
|
tcx,
|
||||||
llcx,
|
&cx,
|
||||||
llmod,
|
|
||||||
"__rust_alloc_error_handler",
|
"__rust_alloc_error_handler",
|
||||||
alloc_error_handler_name(alloc_error_handler_kind),
|
alloc_error_handler_name(alloc_error_handler_kind),
|
||||||
&[usize, usize], // size, align
|
&[usize, usize], // size, align
|
||||||
|
@ -77,21 +74,21 @@ pub(crate) unsafe fn codegen(
|
||||||
unsafe {
|
unsafe {
|
||||||
// __rust_alloc_error_handler_should_panic
|
// __rust_alloc_error_handler_should_panic
|
||||||
let name = OomStrategy::SYMBOL;
|
let name = OomStrategy::SYMBOL;
|
||||||
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_c_char_ptr(), name.len(), i8);
|
let ll_g = cx.declare_global(name, i8);
|
||||||
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
|
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
|
||||||
let val = tcx.sess.opts.unstable_opts.oom.should_panic();
|
let val = tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||||
let llval = llvm::LLVMConstInt(i8, val as u64, False);
|
let llval = llvm::LLVMConstInt(i8, val as u64, False);
|
||||||
llvm::set_initializer(ll_g, llval);
|
llvm::set_initializer(ll_g, llval);
|
||||||
|
|
||||||
let name = NO_ALLOC_SHIM_IS_UNSTABLE;
|
let name = NO_ALLOC_SHIM_IS_UNSTABLE;
|
||||||
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_c_char_ptr(), name.len(), i8);
|
let ll_g = cx.declare_global(name, i8);
|
||||||
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
|
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
|
||||||
let llval = llvm::LLVMConstInt(i8, 0, False);
|
let llval = llvm::LLVMConstInt(i8, 0, False);
|
||||||
llvm::set_initializer(ll_g, llval);
|
llvm::set_initializer(ll_g, llval);
|
||||||
}
|
}
|
||||||
|
|
||||||
if tcx.sess.opts.debuginfo != DebugInfo::None {
|
if tcx.sess.opts.debuginfo != DebugInfo::None {
|
||||||
let dbg_cx = debuginfo::CodegenUnitDebugContext::new(llmod);
|
let dbg_cx = debuginfo::CodegenUnitDebugContext::new(cx.llmod);
|
||||||
debuginfo::metadata::build_compile_unit_di_node(tcx, module_name, &dbg_cx);
|
debuginfo::metadata::build_compile_unit_di_node(tcx, module_name, &dbg_cx);
|
||||||
dbg_cx.finalize(tcx.sess);
|
dbg_cx.finalize(tcx.sess);
|
||||||
}
|
}
|
||||||
|
@ -99,77 +96,64 @@ pub(crate) unsafe fn codegen(
|
||||||
|
|
||||||
fn create_wrapper_function(
|
fn create_wrapper_function(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
llcx: &Context,
|
cx: &SimpleCx<'_>,
|
||||||
llmod: &Module,
|
|
||||||
from_name: &str,
|
from_name: &str,
|
||||||
to_name: &str,
|
to_name: &str,
|
||||||
args: &[&Type],
|
args: &[&Type],
|
||||||
output: Option<&Type>,
|
output: Option<&Type>,
|
||||||
no_return: bool,
|
no_return: bool,
|
||||||
) {
|
) {
|
||||||
unsafe {
|
let ty = cx.type_func(args, output.unwrap_or_else(|| cx.type_void()));
|
||||||
let ty = llvm::LLVMFunctionType(
|
let llfn = declare_simple_fn(
|
||||||
output.unwrap_or_else(|| llvm::LLVMVoidTypeInContext(llcx)),
|
&cx,
|
||||||
args.as_ptr(),
|
from_name,
|
||||||
args.len() as c_uint,
|
llvm::CallConv::CCallConv,
|
||||||
False,
|
llvm::UnnamedAddr::Global,
|
||||||
);
|
llvm::Visibility::from_generic(tcx.sess.default_visibility()),
|
||||||
let llfn = llvm::LLVMRustGetOrInsertFunction(
|
ty,
|
||||||
llmod,
|
);
|
||||||
from_name.as_c_char_ptr(),
|
let no_return = if no_return {
|
||||||
from_name.len(),
|
// -> ! DIFlagNoReturn
|
||||||
ty,
|
let no_return = llvm::AttributeKind::NoReturn.create_attr(cx.llcx);
|
||||||
);
|
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[no_return]);
|
||||||
let no_return = if no_return {
|
Some(no_return)
|
||||||
// -> ! DIFlagNoReturn
|
} else {
|
||||||
let no_return = llvm::AttributeKind::NoReturn.create_attr(llcx);
|
None
|
||||||
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[no_return]);
|
};
|
||||||
Some(no_return)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
llvm::set_visibility(llfn, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
|
if tcx.sess.must_emit_unwind_tables() {
|
||||||
|
let uwtable =
|
||||||
|
attributes::uwtable_attr(cx.llcx, tcx.sess.opts.unstable_opts.use_sync_unwind);
|
||||||
|
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
|
||||||
|
}
|
||||||
|
|
||||||
if tcx.sess.must_emit_unwind_tables() {
|
let callee = declare_simple_fn(
|
||||||
let uwtable =
|
&cx,
|
||||||
attributes::uwtable_attr(llcx, tcx.sess.opts.unstable_opts.use_sync_unwind);
|
to_name,
|
||||||
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
|
llvm::CallConv::CCallConv,
|
||||||
}
|
llvm::UnnamedAddr::Global,
|
||||||
|
llvm::Visibility::Hidden,
|
||||||
|
ty,
|
||||||
|
);
|
||||||
|
if let Some(no_return) = no_return {
|
||||||
|
// -> ! DIFlagNoReturn
|
||||||
|
attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]);
|
||||||
|
}
|
||||||
|
llvm::set_visibility(callee, llvm::Visibility::Hidden);
|
||||||
|
|
||||||
let callee =
|
let llbb = unsafe { llvm::LLVMAppendBasicBlockInContext(cx.llcx, llfn, c"entry".as_ptr()) };
|
||||||
llvm::LLVMRustGetOrInsertFunction(llmod, to_name.as_c_char_ptr(), to_name.len(), ty);
|
|
||||||
if let Some(no_return) = no_return {
|
|
||||||
// -> ! DIFlagNoReturn
|
|
||||||
attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]);
|
|
||||||
}
|
|
||||||
llvm::set_visibility(callee, llvm::Visibility::Hidden);
|
|
||||||
|
|
||||||
let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, c"entry".as_ptr());
|
let mut bx = SBuilder::build(&cx, llbb);
|
||||||
|
let args = args
|
||||||
let llbuilder = llvm::LLVMCreateBuilderInContext(llcx);
|
.iter()
|
||||||
llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb);
|
.enumerate()
|
||||||
let args = args
|
.map(|(i, _)| llvm::get_param(llfn, i as c_uint))
|
||||||
.iter()
|
.collect::<Vec<_>>();
|
||||||
.enumerate()
|
let ret = bx.call(ty, callee, &args, None);
|
||||||
.map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
|
llvm::LLVMSetTailCall(ret, True);
|
||||||
.collect::<Vec<_>>();
|
if output.is_some() {
|
||||||
let ret = llvm::LLVMBuildCallWithOperandBundles(
|
bx.ret(ret);
|
||||||
llbuilder,
|
} else {
|
||||||
ty,
|
bx.ret_void()
|
||||||
callee,
|
|
||||||
args.as_ptr(),
|
|
||||||
args.len() as c_uint,
|
|
||||||
[].as_ptr(),
|
|
||||||
0 as c_uint,
|
|
||||||
c"".as_ptr(),
|
|
||||||
);
|
|
||||||
llvm::LLVMSetTailCall(ret, True);
|
|
||||||
if output.is_some() {
|
|
||||||
llvm::LLVMBuildRet(llbuilder, ret);
|
|
||||||
} else {
|
|
||||||
llvm::LLVMBuildRetVoid(llbuilder);
|
|
||||||
}
|
|
||||||
llvm::LLVMDisposeBuilder(llbuilder);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> Drop for GenericBuilder<'a, 'll, CX> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'll> SBuilder<'a, 'll> {
|
impl<'a, 'll> SBuilder<'a, 'll> {
|
||||||
fn call(
|
pub(crate) fn call(
|
||||||
&mut self,
|
&mut self,
|
||||||
llty: &'ll Type,
|
llty: &'ll Type,
|
||||||
llfn: &'ll Value,
|
llfn: &'ll Value,
|
||||||
|
@ -100,17 +100,17 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
|
||||||
unsafe { llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, UNNAMED) }
|
unsafe { llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, UNNAMED) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ret_void(&mut self) {
|
pub(crate) fn ret_void(&mut self) {
|
||||||
llvm::LLVMBuildRetVoid(self.llbuilder);
|
llvm::LLVMBuildRetVoid(self.llbuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ret(&mut self, v: &'ll Value) {
|
pub(crate) fn ret(&mut self, v: &'ll Value) {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMBuildRet(self.llbuilder, v);
|
llvm::LLVMBuildRet(self.llbuilder, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build(cx: &'a GenericCx<'ll, CX>, llbb: &'ll BasicBlock) -> Self {
|
pub(crate) fn build(cx: &'a GenericCx<'ll, CX>, llbb: &'ll BasicBlock) -> Self {
|
||||||
let bx = Self::with_cx(cx);
|
let bx = Self::with_cx(cx);
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMPositionBuilderAtEnd(bx.llbuilder, llbb);
|
llvm::LLVMPositionBuilderAtEnd(bx.llbuilder, llbb);
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
//! * Use define_* family of methods when you might be defining the Value.
|
//! * Use define_* family of methods when you might be defining the Value.
|
||||||
//! * When in doubt, define.
|
//! * When in doubt, define.
|
||||||
|
|
||||||
|
use std::borrow::Borrow;
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rustc_codegen_ssa::traits::TypeMembershipCodegenMethods;
|
use rustc_codegen_ssa::traits::TypeMembershipCodegenMethods;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
|
@ -22,7 +24,7 @@ use tracing::debug;
|
||||||
|
|
||||||
use crate::abi::FnAbiLlvmExt;
|
use crate::abi::FnAbiLlvmExt;
|
||||||
use crate::common::AsCCharPtr;
|
use crate::common::AsCCharPtr;
|
||||||
use crate::context::{CodegenCx, SimpleCx};
|
use crate::context::{CodegenCx, GenericCx, SCx, SimpleCx};
|
||||||
use crate::llvm::AttributePlace::Function;
|
use crate::llvm::AttributePlace::Function;
|
||||||
use crate::llvm::Visibility;
|
use crate::llvm::Visibility;
|
||||||
use crate::type_::Type;
|
use crate::type_::Type;
|
||||||
|
@ -81,16 +83,25 @@ pub(crate) fn declare_raw_fn<'ll, 'tcx>(
|
||||||
llfn
|
llfn
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
|
||||||
/// Declare a global value.
|
/// Declare a global value.
|
||||||
///
|
///
|
||||||
/// If there’s a value with the same name already declared, the function will
|
/// If there’s a value with the same name already declared, the function will
|
||||||
/// return its Value instead.
|
/// return its Value instead.
|
||||||
pub(crate) fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value {
|
pub(crate) fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value {
|
||||||
debug!("declare_global(name={:?})", name);
|
debug!("declare_global(name={:?})", name);
|
||||||
unsafe { llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_c_char_ptr(), name.len(), ty) }
|
unsafe {
|
||||||
|
llvm::LLVMRustGetOrInsertGlobal(
|
||||||
|
(**self).borrow().llmod,
|
||||||
|
name.as_c_char_ptr(),
|
||||||
|
name.len(),
|
||||||
|
ty,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||||
/// Declare a C ABI function.
|
/// Declare a C ABI function.
|
||||||
///
|
///
|
||||||
/// Only use this for foreign function ABIs and glue. For Rust functions use
|
/// Only use this for foreign function ABIs and glue. For Rust functions use
|
||||||
|
|
|
@ -29,6 +29,7 @@ use std::mem::ManuallyDrop;
|
||||||
|
|
||||||
use back::owned_target_machine::OwnedTargetMachine;
|
use back::owned_target_machine::OwnedTargetMachine;
|
||||||
use back::write::{create_informational_target_machine, create_target_machine};
|
use back::write::{create_informational_target_machine, create_target_machine};
|
||||||
|
use context::SimpleCx;
|
||||||
use errors::{AutoDiffWithoutLTO, ParseTargetMachineConfig};
|
use errors::{AutoDiffWithoutLTO, ParseTargetMachineConfig};
|
||||||
pub(crate) use llvm_util::target_features_cfg;
|
pub(crate) use llvm_util::target_features_cfg;
|
||||||
use rustc_ast::expand::allocator::AllocatorKind;
|
use rustc_ast::expand::allocator::AllocatorKind;
|
||||||
|
@ -116,9 +117,11 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
|
||||||
kind: AllocatorKind,
|
kind: AllocatorKind,
|
||||||
alloc_error_handler_kind: AllocatorKind,
|
alloc_error_handler_kind: AllocatorKind,
|
||||||
) -> ModuleLlvm {
|
) -> ModuleLlvm {
|
||||||
let mut module_llvm = ModuleLlvm::new_metadata(tcx, module_name);
|
let module_llvm = ModuleLlvm::new_metadata(tcx, module_name);
|
||||||
|
let cx =
|
||||||
|
SimpleCx::new(module_llvm.llmod(), &module_llvm.llcx, tcx.data_layout.pointer_size);
|
||||||
unsafe {
|
unsafe {
|
||||||
allocator::codegen(tcx, &mut module_llvm, module_name, kind, alloc_error_handler_kind);
|
allocator::codegen(tcx, cx, module_name, kind, alloc_error_handler_kind);
|
||||||
}
|
}
|
||||||
module_llvm
|
module_llvm
|
||||||
}
|
}
|
||||||
|
|
|
@ -1147,7 +1147,7 @@ unsafe extern "C" {
|
||||||
pub(crate) fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode);
|
pub(crate) fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode);
|
||||||
pub(crate) fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
|
pub(crate) fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
|
||||||
pub(crate) fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
|
pub(crate) fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
|
||||||
pub(crate) fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
|
pub(crate) safe fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
|
||||||
|
|
||||||
// Operations on attributes
|
// Operations on attributes
|
||||||
pub(crate) fn LLVMCreateStringAttribute(
|
pub(crate) fn LLVMCreateStringAttribute(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue