Rollup merge of #137549 - oli-obk:llvm-ffi, r=davidtwco
Clean up various LLVM FFI things in codegen_llvm cc ```@ZuseZ4``` I touched some autodiff parts The major change of this PR is [bfd88ce
](bfd88cead0
) which makes `CodegenCx` generic just like `GenericBuilder` The other commits mostly took advantage of the new feature of making extern functions safe, but also just used some wrappers that were already there and shrunk unsafe blocks. best reviewed commit-by-commit
This commit is contained in:
commit
63c548d82c
26 changed files with 336 additions and 368 deletions
|
@ -654,7 +654,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> AbiBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
|
||||
impl AbiBuilderMethods for Builder<'_, '_, '_> {
|
||||
fn get_param(&mut self, index: usize) -> Self::Value {
|
||||
llvm::get_param(self.llfn(), index as c_uint)
|
||||
}
|
||||
|
|
|
@ -3,33 +3,31 @@ use rustc_ast::expand::allocator::{
|
|||
ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
|
||||
alloc_error_handler_name, default_fn_name, global_fn_name,
|
||||
};
|
||||
use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::{DebugInfo, OomStrategy};
|
||||
|
||||
use crate::common::AsCCharPtr;
|
||||
use crate::llvm::{self, Context, False, Module, True, Type};
|
||||
use crate::{ModuleLlvm, attributes, debuginfo};
|
||||
use crate::builder::SBuilder;
|
||||
use crate::declare::declare_simple_fn;
|
||||
use crate::llvm::{self, False, True, Type};
|
||||
use crate::{SimpleCx, attributes, debuginfo};
|
||||
|
||||
pub(crate) unsafe fn codegen(
|
||||
tcx: TyCtxt<'_>,
|
||||
module_llvm: &mut ModuleLlvm,
|
||||
cx: SimpleCx<'_>,
|
||||
module_name: &str,
|
||||
kind: AllocatorKind,
|
||||
alloc_error_handler_kind: AllocatorKind,
|
||||
) {
|
||||
let llcx = &*module_llvm.llcx;
|
||||
let llmod = module_llvm.llmod();
|
||||
let usize = unsafe {
|
||||
match tcx.sess.target.pointer_width {
|
||||
16 => llvm::LLVMInt16TypeInContext(llcx),
|
||||
32 => llvm::LLVMInt32TypeInContext(llcx),
|
||||
64 => llvm::LLVMInt64TypeInContext(llcx),
|
||||
tws => bug!("Unsupported target word size for int: {}", tws),
|
||||
}
|
||||
let usize = match tcx.sess.target.pointer_width {
|
||||
16 => cx.type_i16(),
|
||||
32 => cx.type_i32(),
|
||||
64 => cx.type_i64(),
|
||||
tws => bug!("Unsupported target word size for int: {}", tws),
|
||||
};
|
||||
let i8 = unsafe { llvm::LLVMInt8TypeInContext(llcx) };
|
||||
let i8p = unsafe { llvm::LLVMPointerTypeInContext(llcx, 0) };
|
||||
let i8 = cx.type_i8();
|
||||
let i8p = cx.type_ptr();
|
||||
|
||||
if kind == AllocatorKind::Default {
|
||||
for method in ALLOCATOR_METHODS {
|
||||
|
@ -58,15 +56,14 @@ pub(crate) unsafe fn codegen(
|
|||
let from_name = global_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
|
||||
create_wrapper_function(
|
||||
tcx,
|
||||
llcx,
|
||||
llmod,
|
||||
&cx,
|
||||
"__rust_alloc_error_handler",
|
||||
alloc_error_handler_name(alloc_error_handler_kind),
|
||||
&[usize, usize], // size, align
|
||||
|
@ -77,21 +74,21 @@ pub(crate) unsafe fn codegen(
|
|||
unsafe {
|
||||
// __rust_alloc_error_handler_should_panic
|
||||
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()));
|
||||
let val = tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||
let llval = llvm::LLVMConstInt(i8, val as u64, False);
|
||||
llvm::set_initializer(ll_g, llval);
|
||||
|
||||
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()));
|
||||
let llval = llvm::LLVMConstInt(i8, 0, False);
|
||||
llvm::set_initializer(ll_g, llval);
|
||||
}
|
||||
|
||||
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);
|
||||
dbg_cx.finalize(tcx.sess);
|
||||
}
|
||||
|
@ -99,77 +96,64 @@ pub(crate) unsafe fn codegen(
|
|||
|
||||
fn create_wrapper_function(
|
||||
tcx: TyCtxt<'_>,
|
||||
llcx: &Context,
|
||||
llmod: &Module,
|
||||
cx: &SimpleCx<'_>,
|
||||
from_name: &str,
|
||||
to_name: &str,
|
||||
args: &[&Type],
|
||||
output: Option<&Type>,
|
||||
no_return: bool,
|
||||
) {
|
||||
unsafe {
|
||||
let ty = llvm::LLVMFunctionType(
|
||||
output.unwrap_or_else(|| llvm::LLVMVoidTypeInContext(llcx)),
|
||||
args.as_ptr(),
|
||||
args.len() as c_uint,
|
||||
False,
|
||||
);
|
||||
let llfn = llvm::LLVMRustGetOrInsertFunction(
|
||||
llmod,
|
||||
from_name.as_c_char_ptr(),
|
||||
from_name.len(),
|
||||
ty,
|
||||
);
|
||||
let no_return = if no_return {
|
||||
// -> ! DIFlagNoReturn
|
||||
let no_return = llvm::AttributeKind::NoReturn.create_attr(llcx);
|
||||
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[no_return]);
|
||||
Some(no_return)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let ty = cx.type_func(args, output.unwrap_or_else(|| cx.type_void()));
|
||||
let llfn = declare_simple_fn(
|
||||
&cx,
|
||||
from_name,
|
||||
llvm::CallConv::CCallConv,
|
||||
llvm::UnnamedAddr::Global,
|
||||
llvm::Visibility::from_generic(tcx.sess.default_visibility()),
|
||||
ty,
|
||||
);
|
||||
let no_return = if no_return {
|
||||
// -> ! DIFlagNoReturn
|
||||
let no_return = llvm::AttributeKind::NoReturn.create_attr(cx.llcx);
|
||||
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 uwtable =
|
||||
attributes::uwtable_attr(llcx, tcx.sess.opts.unstable_opts.use_sync_unwind);
|
||||
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[uwtable]);
|
||||
}
|
||||
let callee = declare_simple_fn(
|
||||
&cx,
|
||||
to_name,
|
||||
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 =
|
||||
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 = unsafe { llvm::LLVMAppendBasicBlockInContext(cx.llcx, llfn, c"entry".as_ptr()) };
|
||||
|
||||
let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, c"entry".as_ptr());
|
||||
|
||||
let llbuilder = llvm::LLVMCreateBuilderInContext(llcx);
|
||||
llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb);
|
||||
let args = args
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
|
||||
.collect::<Vec<_>>();
|
||||
let ret = llvm::LLVMBuildCallWithOperandBundles(
|
||||
llbuilder,
|
||||
ty,
|
||||
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);
|
||||
let mut bx = SBuilder::build(&cx, llbb);
|
||||
let args = args
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, _)| llvm::get_param(llfn, i as c_uint))
|
||||
.collect::<Vec<_>>();
|
||||
let ret = bx.call(ty, callee, &args, None);
|
||||
llvm::LLVMSetTailCall(ret, True);
|
||||
if output.is_some() {
|
||||
bx.ret(ret);
|
||||
} else {
|
||||
bx.ret_void()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
|
||||
use libc::{c_char, c_uint};
|
||||
use rustc_abi::{BackendRepr, Float, Integer, Primitive, Scalar};
|
||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||
use rustc_codegen_ssa::mir::operand::OperandValue;
|
||||
|
@ -483,12 +482,13 @@ pub(crate) fn inline_asm_call<'ll>(
|
|||
|
||||
debug!("Asm Output Type: {:?}", output);
|
||||
let fty = bx.cx.type_func(&argtys, output);
|
||||
unsafe {
|
||||
// Ask LLVM to verify that the constraints are well-formed.
|
||||
let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_c_char_ptr(), cons.len());
|
||||
debug!("constraint verification result: {:?}", constraints_ok);
|
||||
if constraints_ok {
|
||||
let v = llvm::LLVMRustInlineAsm(
|
||||
// Ask LLVM to verify that the constraints are well-formed.
|
||||
let constraints_ok =
|
||||
unsafe { llvm::LLVMRustInlineAsmVerify(fty, cons.as_c_char_ptr(), cons.len()) };
|
||||
debug!("constraint verification result: {:?}", constraints_ok);
|
||||
if constraints_ok {
|
||||
let v = unsafe {
|
||||
llvm::LLVMRustInlineAsm(
|
||||
fty,
|
||||
asm.as_c_char_ptr(),
|
||||
asm.len(),
|
||||
|
@ -498,54 +498,50 @@ pub(crate) fn inline_asm_call<'ll>(
|
|||
alignstack,
|
||||
dia,
|
||||
can_throw,
|
||||
);
|
||||
)
|
||||
};
|
||||
|
||||
let call = if !labels.is_empty() {
|
||||
assert!(catch_funclet.is_none());
|
||||
bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None, None)
|
||||
} else if let Some((catch, funclet)) = catch_funclet {
|
||||
bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet, None)
|
||||
} else {
|
||||
bx.call(fty, None, None, v, inputs, None, None)
|
||||
};
|
||||
|
||||
// Store mark in a metadata node so we can map LLVM errors
|
||||
// back to source locations. See #17552.
|
||||
let key = "srcloc";
|
||||
let kind = llvm::LLVMGetMDKindIDInContext(
|
||||
bx.llcx,
|
||||
key.as_ptr().cast::<c_char>(),
|
||||
key.len() as c_uint,
|
||||
);
|
||||
|
||||
// `srcloc` contains one 64-bit integer for each line of assembly code,
|
||||
// where the lower 32 bits hold the lo byte position and the upper 32 bits
|
||||
// hold the hi byte position.
|
||||
let mut srcloc = vec![];
|
||||
if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 {
|
||||
// LLVM inserts an extra line to add the ".intel_syntax", so add
|
||||
// a dummy srcloc entry for it.
|
||||
//
|
||||
// Don't do this if we only have 1 line span since that may be
|
||||
// due to the asm template string coming from a macro. LLVM will
|
||||
// default to the first srcloc for lines that don't have an
|
||||
// associated srcloc.
|
||||
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0)));
|
||||
}
|
||||
srcloc.extend(line_spans.iter().map(|span| {
|
||||
llvm::LLVMValueAsMetadata(bx.const_u64(
|
||||
u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32),
|
||||
))
|
||||
}));
|
||||
let md = llvm::LLVMMDNodeInContext2(bx.llcx, srcloc.as_ptr(), srcloc.len());
|
||||
let md = llvm::LLVMMetadataAsValue(&bx.llcx, md);
|
||||
llvm::LLVMSetMetadata(call, kind, md);
|
||||
|
||||
Some(call)
|
||||
let call = if !labels.is_empty() {
|
||||
assert!(catch_funclet.is_none());
|
||||
bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None, None)
|
||||
} else if let Some((catch, funclet)) = catch_funclet {
|
||||
bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet, None)
|
||||
} else {
|
||||
// LLVM has detected an issue with our constraints, bail out
|
||||
None
|
||||
bx.call(fty, None, None, v, inputs, None, None)
|
||||
};
|
||||
|
||||
// Store mark in a metadata node so we can map LLVM errors
|
||||
// back to source locations. See #17552.
|
||||
let key = "srcloc";
|
||||
let kind = bx.get_md_kind_id(key);
|
||||
|
||||
// `srcloc` contains one 64-bit integer for each line of assembly code,
|
||||
// where the lower 32 bits hold the lo byte position and the upper 32 bits
|
||||
// hold the hi byte position.
|
||||
let mut srcloc = vec![];
|
||||
if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 {
|
||||
// LLVM inserts an extra line to add the ".intel_syntax", so add
|
||||
// a dummy srcloc entry for it.
|
||||
//
|
||||
// Don't do this if we only have 1 line span since that may be
|
||||
// due to the asm template string coming from a macro. LLVM will
|
||||
// default to the first srcloc for lines that don't have an
|
||||
// associated srcloc.
|
||||
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0)));
|
||||
}
|
||||
srcloc.extend(line_spans.iter().map(|span| {
|
||||
llvm::LLVMValueAsMetadata(
|
||||
bx.const_u64(u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32)),
|
||||
)
|
||||
}));
|
||||
let md = unsafe { llvm::LLVMMDNodeInContext2(bx.llcx, srcloc.as_ptr(), srcloc.len()) };
|
||||
let md = bx.get_metadata_value(md);
|
||||
llvm::LLVMSetMetadata(call, kind, md);
|
||||
|
||||
Some(call)
|
||||
} else {
|
||||
// LLVM has detected an issue with our constraints, bail out
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ use tracing::{debug, instrument};
|
|||
|
||||
use crate::abi::FnAbiLlvmExt;
|
||||
use crate::common::Funclet;
|
||||
use crate::context::{CodegenCx, SimpleCx};
|
||||
use crate::context::{CodegenCx, FullCx, GenericCx, SCx};
|
||||
use crate::llvm::{
|
||||
self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, GEPNoWrapFlags, Metadata, True,
|
||||
};
|
||||
|
@ -40,15 +40,15 @@ use crate::value::Value;
|
|||
use crate::{attributes, llvm_util};
|
||||
|
||||
#[must_use]
|
||||
pub(crate) struct GenericBuilder<'a, 'll, CX: Borrow<SimpleCx<'ll>>> {
|
||||
pub(crate) struct GenericBuilder<'a, 'll, CX: Borrow<SCx<'ll>>> {
|
||||
pub llbuilder: &'ll mut llvm::Builder<'ll>,
|
||||
pub cx: &'a CX,
|
||||
pub cx: &'a GenericCx<'ll, CX>,
|
||||
}
|
||||
|
||||
pub(crate) type SBuilder<'a, 'll> = GenericBuilder<'a, 'll, SimpleCx<'ll>>;
|
||||
pub(crate) type Builder<'a, 'll, 'tcx> = GenericBuilder<'a, 'll, CodegenCx<'ll, 'tcx>>;
|
||||
pub(crate) type SBuilder<'a, 'll> = GenericBuilder<'a, 'll, SCx<'ll>>;
|
||||
pub(crate) type Builder<'a, 'll, 'tcx> = GenericBuilder<'a, 'll, FullCx<'ll, 'tcx>>;
|
||||
|
||||
impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> Drop for GenericBuilder<'a, 'll, CX> {
|
||||
impl<'a, 'll, CX: Borrow<SCx<'ll>>> Drop for GenericBuilder<'a, 'll, CX> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
llvm::LLVMDisposeBuilder(&mut *(self.llbuilder as *mut _));
|
||||
|
@ -57,7 +57,7 @@ impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> Drop for GenericBuilder<'a, 'll, CX> {
|
|||
}
|
||||
|
||||
impl<'a, 'll> SBuilder<'a, 'll> {
|
||||
fn call(
|
||||
pub(crate) fn call(
|
||||
&mut self,
|
||||
llty: &'ll Type,
|
||||
llfn: &'ll Value,
|
||||
|
@ -87,79 +87,36 @@ impl<'a, 'll> SBuilder<'a, 'll> {
|
|||
};
|
||||
call
|
||||
}
|
||||
|
||||
fn with_scx(scx: &'a SimpleCx<'ll>) -> Self {
|
||||
// Create a fresh builder from the simple context.
|
||||
let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(scx.llcx) };
|
||||
SBuilder { llbuilder, cx: scx }
|
||||
}
|
||||
}
|
||||
impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> {
|
||||
|
||||
impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
|
||||
fn with_cx(scx: &'a GenericCx<'ll, CX>) -> Self {
|
||||
// Create a fresh builder from the simple context.
|
||||
let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(scx.deref().borrow().llcx) };
|
||||
GenericBuilder { llbuilder, cx: scx }
|
||||
}
|
||||
|
||||
pub(crate) fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
||||
unsafe { llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, UNNAMED) }
|
||||
}
|
||||
|
||||
fn ret_void(&mut self) {
|
||||
unsafe {
|
||||
llvm::LLVMBuildRetVoid(self.llbuilder);
|
||||
}
|
||||
pub(crate) fn ret_void(&mut self) {
|
||||
llvm::LLVMBuildRetVoid(self.llbuilder);
|
||||
}
|
||||
|
||||
fn ret(&mut self, v: &'ll Value) {
|
||||
pub(crate) fn ret(&mut self, v: &'ll Value) {
|
||||
unsafe {
|
||||
llvm::LLVMBuildRet(self.llbuilder, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a, 'll> SBuilder<'a, 'll> {
|
||||
fn build(cx: &'a SimpleCx<'ll>, llbb: &'ll BasicBlock) -> SBuilder<'a, 'll> {
|
||||
let bx = SBuilder::with_scx(cx);
|
||||
|
||||
pub(crate) fn build(cx: &'a GenericCx<'ll, CX>, llbb: &'ll BasicBlock) -> Self {
|
||||
let bx = Self::with_cx(cx);
|
||||
unsafe {
|
||||
llvm::LLVMPositionBuilderAtEnd(bx.llbuilder, llbb);
|
||||
}
|
||||
bx
|
||||
}
|
||||
|
||||
fn check_call<'b>(
|
||||
&mut self,
|
||||
typ: &str,
|
||||
fn_ty: &'ll Type,
|
||||
llfn: &'ll Value,
|
||||
args: &'b [&'ll Value],
|
||||
) -> Cow<'b, [&'ll Value]> {
|
||||
assert!(
|
||||
self.cx.type_kind(fn_ty) == TypeKind::Function,
|
||||
"builder::{typ} not passed a function, but {fn_ty:?}"
|
||||
);
|
||||
|
||||
let param_tys = self.cx.func_params_types(fn_ty);
|
||||
|
||||
let all_args_match = iter::zip(¶m_tys, args.iter().map(|&v| self.cx.val_ty(v)))
|
||||
.all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
|
||||
|
||||
if all_args_match {
|
||||
return Cow::Borrowed(args);
|
||||
}
|
||||
|
||||
let casted_args: Vec<_> = iter::zip(param_tys, args)
|
||||
.enumerate()
|
||||
.map(|(i, (expected_ty, &actual_val))| {
|
||||
let actual_ty = self.cx.val_ty(actual_val);
|
||||
if expected_ty != actual_ty {
|
||||
debug!(
|
||||
"type mismatch in function call of {:?}. \
|
||||
Expected {:?} for param {}, got {:?}; injecting bitcast",
|
||||
llfn, expected_ty, i, actual_ty
|
||||
);
|
||||
self.bitcast(actual_val, expected_ty)
|
||||
} else {
|
||||
actual_val
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
Cow::Owned(casted_args)
|
||||
}
|
||||
}
|
||||
|
||||
/// Empty string, to be used where LLVM expects an instruction name, indicating
|
||||
|
@ -167,17 +124,17 @@ impl<'a, 'll> SBuilder<'a, 'll> {
|
|||
// FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer.
|
||||
const UNNAMED: *const c_char = c"".as_ptr();
|
||||
|
||||
impl<'ll, 'tcx> BackendTypes for Builder<'_, 'll, 'tcx> {
|
||||
type Value = <CodegenCx<'ll, 'tcx> as BackendTypes>::Value;
|
||||
type Metadata = <CodegenCx<'ll, 'tcx> as BackendTypes>::Metadata;
|
||||
type Function = <CodegenCx<'ll, 'tcx> as BackendTypes>::Function;
|
||||
type BasicBlock = <CodegenCx<'ll, 'tcx> as BackendTypes>::BasicBlock;
|
||||
type Type = <CodegenCx<'ll, 'tcx> as BackendTypes>::Type;
|
||||
type Funclet = <CodegenCx<'ll, 'tcx> as BackendTypes>::Funclet;
|
||||
impl<'ll, CX: Borrow<SCx<'ll>>> BackendTypes for GenericBuilder<'_, 'll, CX> {
|
||||
type Value = <GenericCx<'ll, CX> as BackendTypes>::Value;
|
||||
type Metadata = <GenericCx<'ll, CX> as BackendTypes>::Metadata;
|
||||
type Function = <GenericCx<'ll, CX> as BackendTypes>::Function;
|
||||
type BasicBlock = <GenericCx<'ll, CX> as BackendTypes>::BasicBlock;
|
||||
type Type = <GenericCx<'ll, CX> as BackendTypes>::Type;
|
||||
type Funclet = <GenericCx<'ll, CX> as BackendTypes>::Funclet;
|
||||
|
||||
type DIScope = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIScope;
|
||||
type DILocation = <CodegenCx<'ll, 'tcx> as BackendTypes>::DILocation;
|
||||
type DIVariable = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIVariable;
|
||||
type DIScope = <GenericCx<'ll, CX> as BackendTypes>::DIScope;
|
||||
type DILocation = <GenericCx<'ll, CX> as BackendTypes>::DILocation;
|
||||
type DIVariable = <GenericCx<'ll, CX> as BackendTypes>::DIVariable;
|
||||
}
|
||||
|
||||
impl abi::HasDataLayout for Builder<'_, '_, '_> {
|
||||
|
@ -293,9 +250,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
|
||||
fn ret_void(&mut self) {
|
||||
unsafe {
|
||||
llvm::LLVMBuildRetVoid(self.llbuilder);
|
||||
}
|
||||
llvm::LLVMBuildRetVoid(self.llbuilder);
|
||||
}
|
||||
|
||||
fn ret(&mut self, v: &'ll Value) {
|
||||
|
@ -356,8 +311,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
// This function handles switch instructions with more than 2 targets and it needs to
|
||||
// emit branch weights metadata instead of using the intrinsic.
|
||||
// The values 1 and 2000 are the same as the values used by the `llvm.expect` intrinsic.
|
||||
let cold_weight = unsafe { llvm::LLVMValueAsMetadata(self.cx.const_u32(1)) };
|
||||
let hot_weight = unsafe { llvm::LLVMValueAsMetadata(self.cx.const_u32(2000)) };
|
||||
let cold_weight = llvm::LLVMValueAsMetadata(self.cx.const_u32(1));
|
||||
let hot_weight = llvm::LLVMValueAsMetadata(self.cx.const_u32(2000));
|
||||
let weight =
|
||||
|is_cold: bool| -> &Metadata { if is_cold { cold_weight } else { hot_weight } };
|
||||
|
||||
|
@ -1476,26 +1431,12 @@ impl<'ll> StaticBuilderMethods for Builder<'_, 'll, '_> {
|
|||
}
|
||||
|
||||
impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||
fn build(cx: &'a CodegenCx<'ll, 'tcx>, llbb: &'ll BasicBlock) -> Builder<'a, 'll, 'tcx> {
|
||||
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 }
|
||||
}
|
||||
|
||||
pub(crate) fn llfn(&self) -> &'ll Value {
|
||||
unsafe { llvm::LLVMGetBasicBlockParent(self.llbb()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> {
|
||||
impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
|
||||
fn position_at_start(&mut self, llbb: &'ll BasicBlock) {
|
||||
unsafe {
|
||||
llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
|
||||
|
@ -1525,7 +1466,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> {
|
||||
impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
|
||||
pub(crate) fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
|
||||
}
|
||||
|
@ -1626,9 +1567,7 @@ impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> {
|
|||
let ret = unsafe { llvm::LLVMBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) };
|
||||
ret.expect("LLVM does not have support for catchret")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||
fn check_call<'b>(
|
||||
&mut self,
|
||||
typ: &str,
|
||||
|
@ -1643,7 +1582,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
|||
|
||||
let param_tys = self.cx.func_params_types(fn_ty);
|
||||
|
||||
let all_args_match = iter::zip(¶m_tys, args.iter().map(|&v| self.val_ty(v)))
|
||||
let all_args_match = iter::zip(¶m_tys, args.iter().map(|&v| self.cx.val_ty(v)))
|
||||
.all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
|
||||
|
||||
if all_args_match {
|
||||
|
@ -1653,7 +1592,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
|||
let casted_args: Vec<_> = iter::zip(param_tys, args)
|
||||
.enumerate()
|
||||
.map(|(i, (expected_ty, &actual_val))| {
|
||||
let actual_ty = self.val_ty(actual_val);
|
||||
let actual_ty = self.cx.val_ty(actual_val);
|
||||
if expected_ty != actual_ty {
|
||||
debug!(
|
||||
"type mismatch in function call of {:?}. \
|
||||
|
@ -1669,12 +1608,12 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
|||
|
||||
Cow::Owned(casted_args)
|
||||
}
|
||||
}
|
||||
impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> {
|
||||
|
||||
pub(crate) fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
|
||||
unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||
pub(crate) fn call_intrinsic(&mut self, intrinsic: &str, args: &[&'ll Value]) -> &'ll Value {
|
||||
let (ty, f) = self.cx.get_intrinsic(intrinsic);
|
||||
|
@ -1694,7 +1633,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
|||
self.call_intrinsic(intrinsic, &[self.cx.const_u64(size), ptr]);
|
||||
}
|
||||
}
|
||||
impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> {
|
||||
impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
|
||||
pub(crate) fn phi(
|
||||
&mut self,
|
||||
ty: &'ll Type,
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::ptr;
|
|||
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, AutoDiffItem, DiffActivity, DiffMode};
|
||||
use rustc_codegen_ssa::ModuleCodegen;
|
||||
use rustc_codegen_ssa::back::write::ModuleConfig;
|
||||
use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _;
|
||||
use rustc_errors::FatalError;
|
||||
use tracing::{debug, trace};
|
||||
|
||||
|
@ -286,7 +287,8 @@ pub(crate) fn differentiate<'ll>(
|
|||
}
|
||||
|
||||
let diag_handler = cgcx.create_dcx();
|
||||
let cx = SimpleCx { llmod: module.module_llvm.llmod(), llcx: module.module_llvm.llcx };
|
||||
|
||||
let cx = SimpleCx::new(module.module_llvm.llmod(), module.module_llvm.llcx, cgcx.pointer_size);
|
||||
|
||||
// First of all, did the user try to use autodiff without using the -Zautodiff=Enable flag?
|
||||
if !diff_items.is_empty()
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
//! Code that is useful in various codegen modules.
|
||||
|
||||
use std::borrow::Borrow;
|
||||
|
||||
use libc::{c_char, c_uint};
|
||||
use rustc_abi as abi;
|
||||
use rustc_abi::Primitive::Pointer;
|
||||
|
@ -18,6 +20,7 @@ use tracing::debug;
|
|||
|
||||
use crate::consts::const_alloc_to_llvm;
|
||||
pub(crate) use crate::context::CodegenCx;
|
||||
use crate::context::{GenericCx, SCx};
|
||||
use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, Metadata, True};
|
||||
use crate::type_::Type;
|
||||
use crate::value::Value;
|
||||
|
@ -81,7 +84,7 @@ impl<'ll> Funclet<'ll> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ll> BackendTypes for CodegenCx<'ll, '_> {
|
||||
impl<'ll, CX: Borrow<SCx<'ll>>> BackendTypes for GenericCx<'ll, CX> {
|
||||
type Value = &'ll Value;
|
||||
type Metadata = &'ll Metadata;
|
||||
// FIXME(eddyb) replace this with a `Function` "subclass" of `Value`.
|
||||
|
@ -118,7 +121,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
|
||||
fn const_null(&self, t: &'ll Type) -> &'ll Value {
|
||||
unsafe { llvm::LLVMConstNull(t) }
|
||||
}
|
||||
|
@ -342,7 +345,7 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value {
|
||||
fn const_data_from_alloc(&self, alloc: ConstAllocation<'_>) -> Self::Value {
|
||||
const_alloc_to_llvm(self, alloc, /*static*/ false)
|
||||
}
|
||||
|
||||
|
|
|
@ -490,7 +490,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
llvm::LLVMMDStringInContext2(self.llcx, bytes.as_c_char_ptr(), bytes.len());
|
||||
let data = [section, alloc];
|
||||
let meta = llvm::LLVMMDNodeInContext2(self.llcx, data.as_ptr(), data.len());
|
||||
let val = llvm::LLVMMetadataAsValue(self.llcx, meta);
|
||||
let val = self.get_metadata_value(meta);
|
||||
llvm::LLVMAddNamedMetadataOperand(
|
||||
self.llmod,
|
||||
c"wasm.custom_sections".as_ptr(),
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use std::borrow::Borrow;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::ffi::{CStr, c_char, c_uint};
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Deref;
|
||||
use std::str;
|
||||
|
||||
use rustc_abi::{HasDataLayout, TargetDataLayout, VariantIdx};
|
||||
use rustc_abi::{HasDataLayout, Size, TargetDataLayout, VariantIdx};
|
||||
use rustc_codegen_ssa::back::versioned_llvm_target;
|
||||
use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh};
|
||||
use rustc_codegen_ssa::common::TypeKind;
|
||||
use rustc_codegen_ssa::errors as ssa_errors;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN};
|
||||
|
@ -32,9 +32,9 @@ use smallvec::SmallVec;
|
|||
|
||||
use crate::back::write::to_llvm_code_model;
|
||||
use crate::callee::get_fn;
|
||||
use crate::common::{self, AsCCharPtr};
|
||||
use crate::common::AsCCharPtr;
|
||||
use crate::debuginfo::metadata::apply_vcall_visibility_metadata;
|
||||
use crate::llvm::{Metadata, MetadataType};
|
||||
use crate::llvm::Metadata;
|
||||
use crate::type_::Type;
|
||||
use crate::value::Value;
|
||||
use crate::{attributes, coverageinfo, debuginfo, llvm, llvm_util};
|
||||
|
@ -43,18 +43,19 @@ use crate::{attributes, coverageinfo, debuginfo, llvm, llvm_util};
|
|||
/// However, there are various cx related functions which we want to be available to the builder and
|
||||
/// other compiler pieces. Here we define a small subset which has enough information and can be
|
||||
/// moved around more freely.
|
||||
pub(crate) struct SimpleCx<'ll> {
|
||||
pub(crate) struct SCx<'ll> {
|
||||
pub llmod: &'ll llvm::Module,
|
||||
pub llcx: &'ll llvm::Context,
|
||||
pub isize_ty: &'ll Type,
|
||||
}
|
||||
|
||||
impl<'ll> Borrow<SimpleCx<'ll>> for CodegenCx<'ll, '_> {
|
||||
fn borrow(&self) -> &SimpleCx<'ll> {
|
||||
impl<'ll> Borrow<SCx<'ll>> for FullCx<'ll, '_> {
|
||||
fn borrow(&self) -> &SCx<'ll> {
|
||||
&self.scx
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ll, 'tcx> Deref for CodegenCx<'ll, 'tcx> {
|
||||
impl<'ll, 'tcx> Deref for FullCx<'ll, 'tcx> {
|
||||
type Target = SimpleCx<'ll>;
|
||||
|
||||
#[inline]
|
||||
|
@ -63,10 +64,25 @@ impl<'ll, 'tcx> Deref for CodegenCx<'ll, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct GenericCx<'ll, T: Borrow<SCx<'ll>>>(T, PhantomData<SCx<'ll>>);
|
||||
|
||||
impl<'ll, T: Borrow<SCx<'ll>>> Deref for GenericCx<'ll, T> {
|
||||
type Target = T;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type SimpleCx<'ll> = GenericCx<'ll, SCx<'ll>>;
|
||||
|
||||
/// There is one `CodegenCx` per codegen unit. Each one has its own LLVM
|
||||
/// `llvm::Context` so that several codegen units may be processed in parallel.
|
||||
/// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`.
|
||||
pub(crate) struct CodegenCx<'ll, 'tcx> {
|
||||
pub(crate) type CodegenCx<'ll, 'tcx> = GenericCx<'ll, FullCx<'ll, 'tcx>>;
|
||||
|
||||
pub(crate) struct FullCx<'ll, 'tcx> {
|
||||
pub tcx: TyCtxt<'tcx>,
|
||||
pub scx: SimpleCx<'ll>,
|
||||
pub use_dll_storage_attrs: bool,
|
||||
|
@ -104,8 +120,6 @@ pub(crate) struct CodegenCx<'ll, 'tcx> {
|
|||
/// Mapping of scalar types to llvm types.
|
||||
pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, &'ll Type>>,
|
||||
|
||||
pub isize_ty: &'ll Type,
|
||||
|
||||
/// Extra per-CGU codegen state needed when coverage instrumentation is enabled.
|
||||
pub coverage_cx: Option<coverageinfo::CguCoverageContext<'ll, 'tcx>>,
|
||||
pub dbg_cx: Option<debuginfo::CodegenUnitDebugContext<'ll, 'tcx>>,
|
||||
|
@ -579,33 +593,33 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
None
|
||||
};
|
||||
|
||||
let isize_ty = Type::ix_llcx(llcx, tcx.data_layout.pointer_size.bits());
|
||||
|
||||
CodegenCx {
|
||||
tcx,
|
||||
scx: SimpleCx { llcx, llmod },
|
||||
use_dll_storage_attrs,
|
||||
tls_model,
|
||||
codegen_unit,
|
||||
instances: Default::default(),
|
||||
vtables: Default::default(),
|
||||
const_str_cache: Default::default(),
|
||||
const_globals: Default::default(),
|
||||
statics_to_rauw: RefCell::new(Vec::new()),
|
||||
used_statics: RefCell::new(Vec::new()),
|
||||
compiler_used_statics: RefCell::new(Vec::new()),
|
||||
type_lowering: Default::default(),
|
||||
scalar_lltypes: Default::default(),
|
||||
isize_ty,
|
||||
coverage_cx,
|
||||
dbg_cx,
|
||||
eh_personality: Cell::new(None),
|
||||
eh_catch_typeinfo: Cell::new(None),
|
||||
rust_try_fn: Cell::new(None),
|
||||
intrinsics: Default::default(),
|
||||
local_gen_sym_counter: Cell::new(0),
|
||||
renamed_statics: Default::default(),
|
||||
}
|
||||
GenericCx(
|
||||
FullCx {
|
||||
tcx,
|
||||
scx: SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size),
|
||||
use_dll_storage_attrs,
|
||||
tls_model,
|
||||
codegen_unit,
|
||||
instances: Default::default(),
|
||||
vtables: Default::default(),
|
||||
const_str_cache: Default::default(),
|
||||
const_globals: Default::default(),
|
||||
statics_to_rauw: RefCell::new(Vec::new()),
|
||||
used_statics: RefCell::new(Vec::new()),
|
||||
compiler_used_statics: RefCell::new(Vec::new()),
|
||||
type_lowering: Default::default(),
|
||||
scalar_lltypes: Default::default(),
|
||||
coverage_cx,
|
||||
dbg_cx,
|
||||
eh_personality: Cell::new(None),
|
||||
eh_catch_typeinfo: Cell::new(None),
|
||||
rust_try_fn: Cell::new(None),
|
||||
intrinsics: Default::default(),
|
||||
local_gen_sym_counter: Cell::new(0),
|
||||
renamed_statics: Default::default(),
|
||||
},
|
||||
PhantomData,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn statics_to_rauw(&self) -> &RefCell<Vec<(&'ll Value, &'ll Value)>> {
|
||||
|
@ -628,24 +642,32 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
llvm::set_section(g, c"llvm.metadata");
|
||||
}
|
||||
}
|
||||
impl<'ll> SimpleCx<'ll> {
|
||||
pub(crate) fn val_ty(&self, v: &'ll Value) -> &'ll Type {
|
||||
common::val_ty(v)
|
||||
}
|
||||
|
||||
impl<'ll> SimpleCx<'ll> {
|
||||
pub(crate) fn new(
|
||||
llmod: &'ll llvm::Module,
|
||||
llcx: &'ll llvm::Context,
|
||||
pointer_size: Size,
|
||||
) -> Self {
|
||||
let isize_ty = llvm::Type::ix_llcx(llcx, pointer_size.bits());
|
||||
Self(SCx { llmod, llcx, isize_ty }, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
|
||||
pub(crate) fn get_metadata_value(&self, metadata: &'ll Metadata) -> &'ll Value {
|
||||
unsafe { llvm::LLVMMetadataAsValue(self.llcx, metadata) }
|
||||
llvm::LLVMMetadataAsValue(self.llcx(), metadata)
|
||||
}
|
||||
|
||||
pub(crate) fn get_function(&self, name: &str) -> Option<&'ll Value> {
|
||||
let name = SmallCStr::new(name);
|
||||
unsafe { llvm::LLVMGetNamedFunction(self.llmod, name.as_ptr()) }
|
||||
unsafe { llvm::LLVMGetNamedFunction((**self).borrow().llmod, name.as_ptr()) }
|
||||
}
|
||||
|
||||
pub(crate) fn get_md_kind_id(&self, name: &str) -> u32 {
|
||||
pub(crate) fn get_md_kind_id(&self, name: &str) -> llvm::MetadataKindId {
|
||||
unsafe {
|
||||
llvm::LLVMGetMDKindIDInContext(
|
||||
self.llcx,
|
||||
self.llcx(),
|
||||
name.as_ptr() as *const c_char,
|
||||
name.len() as c_uint,
|
||||
)
|
||||
|
@ -654,13 +676,9 @@ impl<'ll> SimpleCx<'ll> {
|
|||
|
||||
pub(crate) fn create_metadata(&self, name: String) -> Option<&'ll Metadata> {
|
||||
Some(unsafe {
|
||||
llvm::LLVMMDStringInContext2(self.llcx, name.as_ptr() as *const c_char, name.len())
|
||||
llvm::LLVMMDStringInContext2(self.llcx(), name.as_ptr() as *const c_char, name.len())
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn type_kind(&self, ty: &'ll Type) -> TypeKind {
|
||||
unsafe { llvm::LLVMRustGetTypeKind(ty).to_generic() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
|
@ -1203,27 +1221,18 @@ impl CodegenCx<'_, '_> {
|
|||
name.push_str(&(idx as u64).to_base(ALPHANUMERIC_ONLY));
|
||||
name
|
||||
}
|
||||
|
||||
/// A wrapper for [`llvm::LLVMSetMetadata`], but it takes `Metadata` as a parameter instead of `Value`.
|
||||
pub(crate) fn set_metadata<'a>(&self, val: &'a Value, kind_id: MetadataType, md: &'a Metadata) {
|
||||
unsafe {
|
||||
let node = llvm::LLVMMetadataAsValue(&self.llcx, md);
|
||||
llvm::LLVMSetMetadata(val, kind_id as c_uint, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is a duplication of the set_metadata function above. However, so far it's the only one
|
||||
// shared between both contexts, so it doesn't seem worth it to make the Cx generic like we did it
|
||||
// for the Builder.
|
||||
impl SimpleCx<'_> {
|
||||
#[allow(unused)]
|
||||
impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
|
||||
/// A wrapper for [`llvm::LLVMSetMetadata`], but it takes `Metadata` as a parameter instead of `Value`.
|
||||
pub(crate) fn set_metadata<'a>(&self, val: &'a Value, kind_id: MetadataType, md: &'a Metadata) {
|
||||
unsafe {
|
||||
let node = llvm::LLVMMetadataAsValue(&self.llcx, md);
|
||||
llvm::LLVMSetMetadata(val, kind_id as c_uint, node);
|
||||
}
|
||||
pub(crate) fn set_metadata<'a>(
|
||||
&self,
|
||||
val: &'a Value,
|
||||
kind_id: impl Into<llvm::MetadataKindId>,
|
||||
md: &'ll Metadata,
|
||||
) {
|
||||
let node = self.get_metadata_value(md);
|
||||
llvm::LLVMSetMetadata(val, kind_id.into(), node);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::ffi::CString;
|
|||
|
||||
use rustc_abi::Align;
|
||||
use rustc_codegen_ssa::traits::{
|
||||
BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
|
||||
BaseTypeCodegenMethods as _, ConstCodegenMethods, StaticCodegenMethods,
|
||||
};
|
||||
use rustc_middle::mir::coverage::{
|
||||
BasicCoverageBlock, CovTerm, CoverageIdsInfo, Expression, FunctionCoverageInfo, Mapping,
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
//! * Use define_* family of methods when you might be defining the Value.
|
||||
//! * When in doubt, define.
|
||||
|
||||
use std::borrow::Borrow;
|
||||
|
||||
use itertools::Itertools;
|
||||
use rustc_codegen_ssa::traits::TypeMembershipCodegenMethods;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
|
@ -22,7 +24,7 @@ use tracing::debug;
|
|||
|
||||
use crate::abi::FnAbiLlvmExt;
|
||||
use crate::common::AsCCharPtr;
|
||||
use crate::context::{CodegenCx, SimpleCx};
|
||||
use crate::context::{CodegenCx, GenericCx, SCx, SimpleCx};
|
||||
use crate::llvm::AttributePlace::Function;
|
||||
use crate::llvm::Visibility;
|
||||
use crate::type_::Type;
|
||||
|
@ -81,16 +83,25 @@ pub(crate) fn declare_raw_fn<'ll, 'tcx>(
|
|||
llfn
|
||||
}
|
||||
|
||||
impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||
impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
|
||||
/// Declare a global value.
|
||||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
/// return its Value instead.
|
||||
pub(crate) fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value {
|
||||
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.
|
||||
///
|
||||
/// Only use this for foreign function ABIs and glue. For Rust functions use
|
||||
|
|
|
@ -649,7 +649,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
fn type_test(&mut self, pointer: Self::Value, typeid: Self::Metadata) -> Self::Value {
|
||||
// Test the called operand using llvm.type.test intrinsic. The LowerTypeTests link-time
|
||||
// optimization pass replaces calls to this intrinsic with code to test type membership.
|
||||
let typeid = unsafe { llvm::LLVMMetadataAsValue(&self.llcx, typeid) };
|
||||
let typeid = self.get_metadata_value(typeid);
|
||||
self.call_intrinsic("llvm.type.test", &[pointer, typeid])
|
||||
}
|
||||
|
||||
|
@ -659,7 +659,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
vtable_byte_offset: u64,
|
||||
typeid: &'ll Metadata,
|
||||
) -> Self::Value {
|
||||
let typeid = unsafe { llvm::LLVMMetadataAsValue(&self.llcx, typeid) };
|
||||
let typeid = self.get_metadata_value(typeid);
|
||||
let vtable_byte_offset = self.const_i32(vtable_byte_offset as i32);
|
||||
let type_checked_load =
|
||||
self.call_intrinsic("llvm.type.checked.load", &[llvtable, vtable_byte_offset, typeid]);
|
||||
|
|
|
@ -28,6 +28,7 @@ use std::mem::ManuallyDrop;
|
|||
|
||||
use back::owned_target_machine::OwnedTargetMachine;
|
||||
use back::write::{create_informational_target_machine, create_target_machine};
|
||||
use context::SimpleCx;
|
||||
use errors::{AutoDiffWithoutLTO, ParseTargetMachineConfig};
|
||||
pub(crate) use llvm_util::target_features_cfg;
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
|
@ -115,9 +116,11 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
|
|||
kind: AllocatorKind,
|
||||
alloc_error_handler_kind: AllocatorKind,
|
||||
) -> 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 {
|
||||
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
|
||||
}
|
||||
|
|
|
@ -3,13 +3,14 @@
|
|||
|
||||
use libc::{c_char, c_uint};
|
||||
|
||||
use super::MetadataKindId;
|
||||
use super::ffi::{BasicBlock, Metadata, Module, Type, Value};
|
||||
use crate::llvm::Bool;
|
||||
|
||||
#[link(name = "llvm-wrapper", kind = "static")]
|
||||
unsafe extern "C" {
|
||||
// Enzyme
|
||||
pub(crate) fn LLVMRustHasMetadata(I: &Value, KindID: c_uint) -> bool;
|
||||
pub(crate) safe fn LLVMRustHasMetadata(I: &Value, KindID: MetadataKindId) -> bool;
|
||||
pub(crate) fn LLVMRustEraseInstUntilInclusive(BB: &BasicBlock, I: &Value);
|
||||
pub(crate) fn LLVMRustGetLastInstruction<'a>(BB: &BasicBlock) -> Option<&'a Value>;
|
||||
pub(crate) fn LLVMRustDIGetInstMetadata(I: &Value) -> Option<&Metadata>;
|
||||
|
|
|
@ -976,6 +976,16 @@ pub type SelfProfileAfterPassCallback = unsafe extern "C" fn(*mut c_void);
|
|||
pub type GetSymbolsCallback = unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void;
|
||||
pub type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> *mut c_void;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
pub struct MetadataKindId(c_uint);
|
||||
|
||||
impl From<MetadataType> for MetadataKindId {
|
||||
fn from(value: MetadataType) -> Self {
|
||||
Self(value as c_uint)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" {
|
||||
// Create and destroy contexts.
|
||||
pub(crate) fn LLVMContextDispose(C: &'static mut Context);
|
||||
|
@ -983,7 +993,7 @@ unsafe extern "C" {
|
|||
C: &Context,
|
||||
Name: *const c_char,
|
||||
SLen: c_uint,
|
||||
) -> c_uint;
|
||||
) -> MetadataKindId;
|
||||
|
||||
// Create modules.
|
||||
pub(crate) fn LLVMModuleCreateWithNameInContext(
|
||||
|
@ -1050,9 +1060,9 @@ unsafe extern "C" {
|
|||
pub(crate) fn LLVMGetValueName2(Val: &Value, Length: *mut size_t) -> *const c_char;
|
||||
pub(crate) fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t);
|
||||
pub(crate) fn LLVMReplaceAllUsesWith<'a>(OldVal: &'a Value, NewVal: &'a Value);
|
||||
pub(crate) fn LLVMSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Node: &'a Value);
|
||||
pub(crate) safe fn LLVMSetMetadata<'a>(Val: &'a Value, KindID: MetadataKindId, Node: &'a Value);
|
||||
pub(crate) fn LLVMGlobalSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
|
||||
pub(crate) fn LLVMValueAsMetadata(Node: &Value) -> &Metadata;
|
||||
pub(crate) safe fn LLVMValueAsMetadata(Node: &Value) -> &Metadata;
|
||||
|
||||
// Operations on constants of any type
|
||||
pub(crate) fn LLVMConstNull(Ty: &Type) -> &Value;
|
||||
|
@ -1146,7 +1156,7 @@ unsafe extern "C" {
|
|||
pub(crate) fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode);
|
||||
pub(crate) fn LLVMIsGlobalConstant(GlobalVar: &Value) -> 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
|
||||
pub(crate) fn LLVMCreateStringAttribute(
|
||||
|
@ -1203,7 +1213,7 @@ unsafe extern "C" {
|
|||
pub(crate) fn LLVMGetCurrentDebugLocation2<'a>(Builder: &Builder<'a>) -> Option<&'a Metadata>;
|
||||
|
||||
// Terminators
|
||||
pub(crate) fn LLVMBuildRetVoid<'a>(B: &Builder<'a>) -> &'a Value;
|
||||
pub(crate) safe fn LLVMBuildRetVoid<'a>(B: &Builder<'a>) -> &'a Value;
|
||||
pub(crate) fn LLVMBuildRet<'a>(B: &Builder<'a>, V: &'a Value) -> &'a Value;
|
||||
pub(crate) fn LLVMBuildBr<'a>(B: &Builder<'a>, Dest: &'a BasicBlock) -> &'a Value;
|
||||
pub(crate) fn LLVMBuildCondBr<'a>(
|
||||
|
@ -1679,7 +1689,7 @@ unsafe extern "C" {
|
|||
Packed: Bool,
|
||||
);
|
||||
|
||||
pub(crate) fn LLVMMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value;
|
||||
pub(crate) safe fn LLVMMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value;
|
||||
|
||||
pub(crate) fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr);
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::borrow::Borrow;
|
||||
use std::{fmt, ptr};
|
||||
|
||||
use libc::{c_char, c_uint};
|
||||
|
@ -11,7 +12,7 @@ use rustc_middle::ty::{self, Ty};
|
|||
use rustc_target::callconv::{CastTarget, FnAbi};
|
||||
|
||||
use crate::abi::{FnAbiLlvmExt, LlvmType};
|
||||
use crate::context::{CodegenCx, SimpleCx};
|
||||
use crate::context::{CodegenCx, GenericCx, SCx};
|
||||
pub(crate) use crate::llvm::Type;
|
||||
use crate::llvm::{Bool, False, Metadata, True};
|
||||
use crate::type_of::LayoutLlvmExt;
|
||||
|
@ -36,29 +37,29 @@ impl fmt::Debug for Type {
|
|||
}
|
||||
|
||||
impl<'ll> CodegenCx<'ll, '_> {}
|
||||
impl<'ll> SimpleCx<'ll> {
|
||||
impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
|
||||
pub(crate) fn type_named_struct(&self, name: &str) -> &'ll Type {
|
||||
let name = SmallCStr::new(name);
|
||||
unsafe { llvm::LLVMStructCreateNamed(self.llcx, name.as_ptr()) }
|
||||
unsafe { llvm::LLVMStructCreateNamed(self.llcx(), name.as_ptr()) }
|
||||
}
|
||||
|
||||
pub(crate) fn set_struct_body(&self, ty: &'ll Type, els: &[&'ll Type], packed: bool) {
|
||||
unsafe { llvm::LLVMStructSetBody(ty, els.as_ptr(), els.len() as c_uint, packed as Bool) }
|
||||
}
|
||||
pub(crate) fn type_void(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMVoidTypeInContext(self.llcx) }
|
||||
unsafe { llvm::LLVMVoidTypeInContext(self.llcx()) }
|
||||
}
|
||||
pub(crate) fn type_token(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMTokenTypeInContext(self.llcx) }
|
||||
unsafe { llvm::LLVMTokenTypeInContext(self.llcx()) }
|
||||
}
|
||||
|
||||
pub(crate) fn type_metadata(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMMetadataTypeInContext(self.llcx) }
|
||||
unsafe { llvm::LLVMMetadataTypeInContext(self.llcx()) }
|
||||
}
|
||||
|
||||
///x Creates an integer type with the given number of bits, e.g., i24
|
||||
pub(crate) fn type_ix(&self, num_bits: u64) -> &'ll Type {
|
||||
unsafe { llvm::LLVMIntTypeInContext(self.llcx, num_bits as c_uint) }
|
||||
unsafe { llvm::LLVMIntTypeInContext(self.llcx(), num_bits as c_uint) }
|
||||
}
|
||||
|
||||
pub(crate) fn type_vector(&self, ty: &'ll Type, len: u64) -> &'ll Type {
|
||||
|
@ -121,19 +122,28 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
self.type_array(self.type_from_integer(unit), size / unit_size)
|
||||
}
|
||||
}
|
||||
impl<'ll> SimpleCx<'ll> {
|
||||
|
||||
impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
|
||||
pub(crate) fn llcx(&self) -> &'ll llvm::Context {
|
||||
(**self).borrow().llcx
|
||||
}
|
||||
|
||||
pub(crate) fn isize_ty(&self) -> &'ll Type {
|
||||
(**self).borrow().isize_ty
|
||||
}
|
||||
|
||||
pub(crate) fn type_variadic_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
|
||||
unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) }
|
||||
}
|
||||
|
||||
pub(crate) fn type_i1(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMInt1TypeInContext(self.llcx) }
|
||||
unsafe { llvm::LLVMInt1TypeInContext(self.llcx()) }
|
||||
}
|
||||
|
||||
pub(crate) fn type_struct(&self, els: &[&'ll Type], packed: bool) -> &'ll Type {
|
||||
unsafe {
|
||||
llvm::LLVMStructTypeInContext(
|
||||
self.llcx,
|
||||
self.llcx(),
|
||||
els.as_ptr(),
|
||||
els.len() as c_uint,
|
||||
packed as Bool,
|
||||
|
@ -142,45 +152,45 @@ impl<'ll> SimpleCx<'ll> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ll, 'tcx> BaseTypeCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
impl<'ll, CX: Borrow<SCx<'ll>>> BaseTypeCodegenMethods for GenericCx<'ll, CX> {
|
||||
fn type_i8(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMInt8TypeInContext(self.llcx) }
|
||||
unsafe { llvm::LLVMInt8TypeInContext(self.llcx()) }
|
||||
}
|
||||
|
||||
fn type_i16(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMInt16TypeInContext(self.llcx) }
|
||||
unsafe { llvm::LLVMInt16TypeInContext(self.llcx()) }
|
||||
}
|
||||
|
||||
fn type_i32(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMInt32TypeInContext(self.llcx) }
|
||||
unsafe { llvm::LLVMInt32TypeInContext(self.llcx()) }
|
||||
}
|
||||
|
||||
fn type_i64(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMInt64TypeInContext(self.llcx) }
|
||||
unsafe { llvm::LLVMInt64TypeInContext(self.llcx()) }
|
||||
}
|
||||
|
||||
fn type_i128(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMIntTypeInContext(self.llcx, 128) }
|
||||
unsafe { llvm::LLVMIntTypeInContext(self.llcx(), 128) }
|
||||
}
|
||||
|
||||
fn type_isize(&self) -> &'ll Type {
|
||||
self.isize_ty
|
||||
self.isize_ty()
|
||||
}
|
||||
|
||||
fn type_f16(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMHalfTypeInContext(self.llcx) }
|
||||
unsafe { llvm::LLVMHalfTypeInContext(self.llcx()) }
|
||||
}
|
||||
|
||||
fn type_f32(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMFloatTypeInContext(self.llcx) }
|
||||
unsafe { llvm::LLVMFloatTypeInContext(self.llcx()) }
|
||||
}
|
||||
|
||||
fn type_f64(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMDoubleTypeInContext(self.llcx) }
|
||||
unsafe { llvm::LLVMDoubleTypeInContext(self.llcx()) }
|
||||
}
|
||||
|
||||
fn type_f128(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMFP128TypeInContext(self.llcx) }
|
||||
unsafe { llvm::LLVMFP128TypeInContext(self.llcx()) }
|
||||
}
|
||||
|
||||
fn type_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
|
||||
|
@ -196,7 +206,7 @@ impl<'ll, 'tcx> BaseTypeCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
}
|
||||
|
||||
fn type_ptr_ext(&self, address_space: AddressSpace) -> &'ll Type {
|
||||
unsafe { llvm::LLVMPointerTypeInContext(self.llcx, address_space.0) }
|
||||
unsafe { llvm::LLVMPointerTypeInContext(self.llcx(), address_space.0) }
|
||||
}
|
||||
|
||||
fn element_type(&self, ty: &'ll Type) -> &'ll Type {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue