Make CodegenCx and Builder generic
Co-authored-by: Oli Scherer <github35764891676564198441@oli-obk.de>
This commit is contained in:
parent
a48e7b0057
commit
386c233858
10 changed files with 239 additions and 56 deletions
|
@ -442,7 +442,6 @@ impl WriteBackendMethods for GccCodegenBackend {
|
||||||
}
|
}
|
||||||
fn autodiff(
|
fn autodiff(
|
||||||
_cgcx: &CodegenContext<Self>,
|
_cgcx: &CodegenContext<Self>,
|
||||||
_tcx: TyCtxt<'_>,
|
|
||||||
_module: &ModuleCodegen<Self::Module>,
|
_module: &ModuleCodegen<Self::Module>,
|
||||||
_diff_fncs: Vec<AutoDiffItem>,
|
_diff_fncs: Vec<AutoDiffItem>,
|
||||||
_config: &ModuleConfig,
|
_config: &ModuleConfig,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::{Borrow, Cow};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::{iter, ptr};
|
use std::{iter, ptr};
|
||||||
|
|
||||||
|
@ -31,20 +31,22 @@ use tracing::{debug, instrument};
|
||||||
use crate::abi::FnAbiLlvmExt;
|
use crate::abi::FnAbiLlvmExt;
|
||||||
use crate::attributes;
|
use crate::attributes;
|
||||||
use crate::common::Funclet;
|
use crate::common::Funclet;
|
||||||
use crate::context::CodegenCx;
|
use crate::context::{CodegenCx, SimpleCx};
|
||||||
use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, True};
|
use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, True};
|
||||||
use crate::type_::Type;
|
use crate::type_::Type;
|
||||||
use crate::type_of::LayoutLlvmExt;
|
use crate::type_of::LayoutLlvmExt;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
|
|
||||||
// All Builders must have an llfn associated with them
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub(crate) struct Builder<'a, 'll, 'tcx> {
|
pub(crate) struct GenericBuilder<'a, 'll, CX: Borrow<SimpleCx<'ll>>> {
|
||||||
pub llbuilder: &'ll mut llvm::Builder<'ll>,
|
pub llbuilder: &'ll mut llvm::Builder<'ll>,
|
||||||
pub cx: &'a CodegenCx<'ll, 'tcx>,
|
pub cx: &'a CX,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Builder<'_, '_, '_> {
|
pub(crate) type SBuilder<'a, 'll> = GenericBuilder<'a, 'll, SimpleCx<'ll>>;
|
||||||
|
pub(crate) type Builder<'a, 'll, 'tcx> = GenericBuilder<'a, 'll, CodegenCx<'ll, 'tcx>>;
|
||||||
|
|
||||||
|
impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> Drop for GenericBuilder<'a, 'll, CX> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMDisposeBuilder(&mut *(self.llbuilder as *mut _));
|
llvm::LLVMDisposeBuilder(&mut *(self.llbuilder as *mut _));
|
||||||
|
@ -52,6 +54,112 @@ impl Drop for Builder<'_, '_, '_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'll> SBuilder<'a, 'll> {
|
||||||
|
fn call(
|
||||||
|
&mut self,
|
||||||
|
llty: &'ll Type,
|
||||||
|
llfn: &'ll Value,
|
||||||
|
args: &[&'ll Value],
|
||||||
|
funclet: Option<&Funclet<'ll>>,
|
||||||
|
) -> &'ll Value {
|
||||||
|
debug!("call {:?} with args ({:?})", llfn, args);
|
||||||
|
|
||||||
|
let args = self.check_call("call", llty, llfn, args);
|
||||||
|
let funclet_bundle = funclet.map(|funclet| funclet.bundle());
|
||||||
|
let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
|
||||||
|
if let Some(funclet_bundle) = funclet_bundle {
|
||||||
|
bundles.push(funclet_bundle);
|
||||||
|
}
|
||||||
|
|
||||||
|
let call = unsafe {
|
||||||
|
llvm::LLVMBuildCallWithOperandBundles(
|
||||||
|
self.llbuilder,
|
||||||
|
llty,
|
||||||
|
llfn,
|
||||||
|
args.as_ptr() as *const &llvm::Value,
|
||||||
|
args.len() as c_uint,
|
||||||
|
bundles.as_ptr(),
|
||||||
|
bundles.len() as c_uint,
|
||||||
|
c"".as_ptr(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
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> {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
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
|
/// Empty string, to be used where LLVM expects an instruction name, indicating
|
||||||
/// that the instruction is to be left unnamed (i.e. numbered, in textual IR).
|
/// that the instruction is to be left unnamed (i.e. numbered, in textual IR).
|
||||||
// FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer.
|
// FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer.
|
||||||
|
@ -1222,6 +1330,14 @@ impl<'ll> StaticBuilderMethods for Builder<'_, 'll, '_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
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 {
|
fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self {
|
||||||
// Create a fresh builder from the crate context.
|
// Create a fresh builder from the crate context.
|
||||||
let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(cx.llcx) };
|
let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(cx.llcx) };
|
||||||
|
@ -1231,13 +1347,16 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||||
pub(crate) fn llfn(&self) -> &'ll Value {
|
pub(crate) fn llfn(&self) -> &'ll Value {
|
||||||
unsafe { llvm::LLVMGetBasicBlockParent(self.llbb()) }
|
unsafe { llvm::LLVMGetBasicBlockParent(self.llbb()) }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> {
|
||||||
fn position_at_start(&mut self, llbb: &'ll BasicBlock) {
|
fn position_at_start(&mut self, llbb: &'ll BasicBlock) {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
|
llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||||
fn align_metadata(&mut self, load: &'ll Value, align: Align) {
|
fn align_metadata(&mut self, load: &'ll Value, align: Align) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let md = [llvm::LLVMValueAsMetadata(self.cx.const_u64(align.bytes()))];
|
let md = [llvm::LLVMValueAsMetadata(self.cx.const_u64(align.bytes()))];
|
||||||
|
@ -1259,7 +1378,8 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||||
self.set_metadata(inst, llvm::MD_unpredictable, md);
|
self.set_metadata(inst, llvm::MD_unpredictable, md);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> {
|
||||||
pub(crate) fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
pub(crate) fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||||
unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
|
unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
|
||||||
}
|
}
|
||||||
|
@ -1360,7 +1480,9 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||||
let ret = unsafe { llvm::LLVMBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) };
|
let ret = unsafe { llvm::LLVMBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) };
|
||||||
ret.expect("LLVM does not have support for catchret")
|
ret.expect("LLVM does not have support for catchret")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||||
fn check_call<'b>(
|
fn check_call<'b>(
|
||||||
&mut self,
|
&mut self,
|
||||||
typ: &str,
|
typ: &str,
|
||||||
|
@ -1401,11 +1523,13 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||||
|
|
||||||
Cow::Owned(casted_args)
|
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 {
|
pub(crate) fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
|
||||||
unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED) }
|
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 {
|
pub(crate) fn call_intrinsic(&mut self, intrinsic: &str, args: &[&'ll Value]) -> &'ll Value {
|
||||||
let (ty, f) = self.cx.get_intrinsic(intrinsic);
|
let (ty, f) = self.cx.get_intrinsic(intrinsic);
|
||||||
self.call(ty, None, None, f, args, None, None)
|
self.call(ty, None, None, f, args, None, None)
|
||||||
|
@ -1423,7 +1547,8 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||||
|
|
||||||
self.call_intrinsic(intrinsic, &[self.cx.const_u64(size), ptr]);
|
self.call_intrinsic(intrinsic, &[self.cx.const_u64(size), ptr]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> {
|
||||||
pub(crate) fn phi(
|
pub(crate) fn phi(
|
||||||
&mut self,
|
&mut self,
|
||||||
ty: &'ll Type,
|
ty: &'ll Type,
|
||||||
|
@ -1443,7 +1568,8 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||||
llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
|
llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||||
fn fptoint_sat(&mut self, signed: bool, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
fn fptoint_sat(&mut self, signed: bool, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
||||||
let src_ty = self.cx.val_ty(val);
|
let src_ty = self.cx.val_ty(val);
|
||||||
let (float_ty, int_ty, vector_length) = if self.cx.type_kind(src_ty) == TypeKind::Vector {
|
let (float_ty, int_ty, vector_length) = if self.cx.type_kind(src_ty) == TypeKind::Vector {
|
||||||
|
|
|
@ -3,20 +3,19 @@ use std::ptr;
|
||||||
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, AutoDiffItem, DiffActivity, DiffMode};
|
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, AutoDiffItem, DiffActivity, DiffMode};
|
||||||
use rustc_codegen_ssa::ModuleCodegen;
|
use rustc_codegen_ssa::ModuleCodegen;
|
||||||
use rustc_codegen_ssa::back::write::ModuleConfig;
|
use rustc_codegen_ssa::back::write::ModuleConfig;
|
||||||
use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods};
|
|
||||||
use rustc_errors::FatalError;
|
use rustc_errors::FatalError;
|
||||||
use rustc_middle::ty::TyCtxt;
|
|
||||||
use rustc_session::config::Lto;
|
use rustc_session::config::Lto;
|
||||||
use tracing::{debug, trace};
|
use tracing::{debug, trace};
|
||||||
|
|
||||||
use crate::back::write::{llvm_err, llvm_optimize};
|
use crate::back::write::{llvm_err, llvm_optimize};
|
||||||
use crate::builder::Builder;
|
use crate::builder::SBuilder;
|
||||||
use crate::declare::declare_raw_fn;
|
use crate::context::SimpleCx;
|
||||||
|
use crate::declare::declare_simple_fn;
|
||||||
use crate::errors::LlvmError;
|
use crate::errors::LlvmError;
|
||||||
use crate::llvm::AttributePlace::Function;
|
use crate::llvm::AttributePlace::Function;
|
||||||
use crate::llvm::{Metadata, True};
|
use crate::llvm::{Metadata, True};
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::{CodegenContext, LlvmCodegenBackend, ModuleLlvm, attributes, context, llvm};
|
use crate::{CodegenContext, LlvmCodegenBackend, ModuleLlvm, attributes, llvm};
|
||||||
|
|
||||||
fn get_params(fnc: &Value) -> Vec<&Value> {
|
fn get_params(fnc: &Value) -> Vec<&Value> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -38,8 +37,8 @@ fn get_params(fnc: &Value) -> Vec<&Value> {
|
||||||
/// [^1]: <https://enzyme.mit.edu/getting_started/CallingConvention/>
|
/// [^1]: <https://enzyme.mit.edu/getting_started/CallingConvention/>
|
||||||
// FIXME(ZuseZ4): `outer_fn` should include upstream safety checks to
|
// FIXME(ZuseZ4): `outer_fn` should include upstream safety checks to
|
||||||
// cover some assumptions of enzyme/autodiff, which could lead to UB otherwise.
|
// cover some assumptions of enzyme/autodiff, which could lead to UB otherwise.
|
||||||
fn generate_enzyme_call<'ll, 'tcx>(
|
fn generate_enzyme_call<'ll>(
|
||||||
cx: &context::CodegenCx<'ll, 'tcx>,
|
cx: &SimpleCx<'ll>,
|
||||||
fn_to_diff: &'ll Value,
|
fn_to_diff: &'ll Value,
|
||||||
outer_fn: &'ll Value,
|
outer_fn: &'ll Value,
|
||||||
attrs: AutoDiffAttrs,
|
attrs: AutoDiffAttrs,
|
||||||
|
@ -112,7 +111,7 @@ fn generate_enzyme_call<'ll, 'tcx>(
|
||||||
//FIXME(ZuseZ4): the CC/Addr/Vis values are best effort guesses, we should look at tests and
|
//FIXME(ZuseZ4): the CC/Addr/Vis values are best effort guesses, we should look at tests and
|
||||||
// think a bit more about what should go here.
|
// think a bit more about what should go here.
|
||||||
let cc = llvm::LLVMGetFunctionCallConv(outer_fn);
|
let cc = llvm::LLVMGetFunctionCallConv(outer_fn);
|
||||||
let ad_fn = declare_raw_fn(
|
let ad_fn = declare_simple_fn(
|
||||||
cx,
|
cx,
|
||||||
&ad_name,
|
&ad_name,
|
||||||
llvm::CallConv::try_from(cc).expect("invalid callconv"),
|
llvm::CallConv::try_from(cc).expect("invalid callconv"),
|
||||||
|
@ -132,7 +131,7 @@ fn generate_enzyme_call<'ll, 'tcx>(
|
||||||
llvm::LLVMRustEraseInstFromParent(br);
|
llvm::LLVMRustEraseInstFromParent(br);
|
||||||
|
|
||||||
let last_inst = llvm::LLVMRustGetLastInstruction(entry).unwrap();
|
let last_inst = llvm::LLVMRustGetLastInstruction(entry).unwrap();
|
||||||
let mut builder = Builder::build(cx, entry);
|
let mut builder = SBuilder::build(cx, entry);
|
||||||
|
|
||||||
let num_args = llvm::LLVMCountParams(&fn_to_diff);
|
let num_args = llvm::LLVMCountParams(&fn_to_diff);
|
||||||
let mut args = Vec::with_capacity(num_args as usize + 1);
|
let mut args = Vec::with_capacity(num_args as usize + 1);
|
||||||
|
@ -236,7 +235,7 @@ fn generate_enzyme_call<'ll, 'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let call = builder.call(enzyme_ty, None, None, ad_fn, &args, None, None);
|
let call = builder.call(enzyme_ty, ad_fn, &args, None);
|
||||||
|
|
||||||
// This part is a bit iffy. LLVM requires that a call to an inlineable function has some
|
// This part is a bit iffy. LLVM requires that a call to an inlineable function has some
|
||||||
// metadata attachted to it, but we just created this code oota. Given that the
|
// metadata attachted to it, but we just created this code oota. Given that the
|
||||||
|
@ -274,10 +273,9 @@ fn generate_enzyme_call<'ll, 'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn differentiate<'ll, 'tcx>(
|
pub(crate) fn differentiate<'ll>(
|
||||||
module: &'ll ModuleCodegen<ModuleLlvm>,
|
module: &'ll ModuleCodegen<ModuleLlvm>,
|
||||||
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
diff_items: Vec<AutoDiffItem>,
|
diff_items: Vec<AutoDiffItem>,
|
||||||
config: &ModuleConfig,
|
config: &ModuleConfig,
|
||||||
) -> Result<(), FatalError> {
|
) -> Result<(), FatalError> {
|
||||||
|
@ -286,8 +284,7 @@ pub(crate) fn differentiate<'ll, 'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
let diag_handler = cgcx.create_dcx();
|
let diag_handler = cgcx.create_dcx();
|
||||||
let (_, cgus) = tcx.collect_and_partition_mono_items(());
|
let cx = SimpleCx { llmod: module.module_llvm.llmod(), llcx: module.module_llvm.llcx };
|
||||||
let cx = context::CodegenCx::new(tcx, &cgus.first().unwrap(), &module.module_llvm);
|
|
||||||
|
|
||||||
// Before dumping the module, we want all the TypeTrees to become part of the module.
|
// Before dumping the module, we want all the TypeTrees to become part of the module.
|
||||||
for item in diff_items.iter() {
|
for item in diff_items.iter() {
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::ffi::{CStr, c_char, c_uint};
|
use std::ffi::{CStr, c_char, c_uint};
|
||||||
|
use std::ops::Deref;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use rustc_abi::{HasDataLayout, TargetDataLayout, VariantIdx};
|
use rustc_abi::{HasDataLayout, TargetDataLayout, VariantIdx};
|
||||||
use rustc_codegen_ssa::back::versioned_llvm_target;
|
use rustc_codegen_ssa::back::versioned_llvm_target;
|
||||||
use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh};
|
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::errors as ssa_errors;
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN};
|
use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN};
|
||||||
|
@ -30,23 +32,46 @@ use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::back::write::to_llvm_code_model;
|
use crate::back::write::to_llvm_code_model;
|
||||||
use crate::callee::get_fn;
|
use crate::callee::get_fn;
|
||||||
use crate::common::AsCCharPtr;
|
use crate::common::{self, AsCCharPtr};
|
||||||
use crate::debuginfo::metadata::apply_vcall_visibility_metadata;
|
use crate::debuginfo::metadata::apply_vcall_visibility_metadata;
|
||||||
use crate::llvm::{Metadata, MetadataType};
|
use crate::llvm::{Metadata, MetadataType};
|
||||||
use crate::type_::Type;
|
use crate::type_::Type;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::{attributes, coverageinfo, debuginfo, llvm, llvm_util};
|
use crate::{attributes, coverageinfo, debuginfo, llvm, llvm_util};
|
||||||
|
|
||||||
|
/// `TyCtxt` (and related cache datastructures) can't be move between threads.
|
||||||
|
/// 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 llmod: &'ll llvm::Module,
|
||||||
|
pub llcx: &'ll llvm::Context,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ll> Borrow<SimpleCx<'ll>> for CodegenCx<'ll, '_> {
|
||||||
|
fn borrow(&self) -> &SimpleCx<'ll> {
|
||||||
|
&self.scx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ll, 'tcx> Deref for CodegenCx<'ll, 'tcx> {
|
||||||
|
type Target = SimpleCx<'ll>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.scx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// There is one `CodegenCx` per codegen unit. Each one has its own LLVM
|
/// 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.
|
/// `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`.
|
/// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`.
|
||||||
pub(crate) struct CodegenCx<'ll, 'tcx> {
|
pub(crate) struct CodegenCx<'ll, 'tcx> {
|
||||||
pub tcx: TyCtxt<'tcx>,
|
pub tcx: TyCtxt<'tcx>,
|
||||||
|
pub scx: SimpleCx<'ll>,
|
||||||
pub use_dll_storage_attrs: bool,
|
pub use_dll_storage_attrs: bool,
|
||||||
pub tls_model: llvm::ThreadLocalMode,
|
pub tls_model: llvm::ThreadLocalMode,
|
||||||
|
|
||||||
pub llmod: &'ll llvm::Module,
|
|
||||||
pub llcx: &'ll llvm::Context,
|
|
||||||
pub codegen_unit: &'tcx CodegenUnit<'tcx>,
|
pub codegen_unit: &'tcx CodegenUnit<'tcx>,
|
||||||
|
|
||||||
/// Cache instances of monomorphic and polymorphic items
|
/// Cache instances of monomorphic and polymorphic items
|
||||||
|
@ -553,10 +578,9 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||||
|
|
||||||
CodegenCx {
|
CodegenCx {
|
||||||
tcx,
|
tcx,
|
||||||
|
scx: SimpleCx { llcx, llmod },
|
||||||
use_dll_storage_attrs,
|
use_dll_storage_attrs,
|
||||||
tls_model,
|
tls_model,
|
||||||
llmod,
|
|
||||||
llcx,
|
|
||||||
codegen_unit,
|
codegen_unit,
|
||||||
instances: Default::default(),
|
instances: Default::default(),
|
||||||
vtables: Default::default(),
|
vtables: Default::default(),
|
||||||
|
@ -600,6 +624,11 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||||
llvm::set_section(g, c"llvm.metadata");
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn get_metadata_value(&self, metadata: &'ll Metadata) -> &'ll Value {
|
pub(crate) fn get_metadata_value(&self, metadata: &'ll Metadata) -> &'ll Value {
|
||||||
unsafe { llvm::LLVMMetadataAsValue(self.llcx, metadata) }
|
unsafe { llvm::LLVMMetadataAsValue(self.llcx, metadata) }
|
||||||
|
@ -625,6 +654,10 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||||
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> {
|
impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
|
@ -1176,6 +1209,20 @@ impl CodegenCx<'_, '_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)]
|
||||||
|
/// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HasDataLayout for CodegenCx<'_, '_> {
|
impl HasDataLayout for CodegenCx<'_, '_> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn data_layout(&self) -> &TargetDataLayout {
|
fn data_layout(&self) -> &TargetDataLayout {
|
||||||
|
|
|
@ -21,26 +21,26 @@ use tracing::debug;
|
||||||
|
|
||||||
use crate::abi::{FnAbi, FnAbiLlvmExt};
|
use crate::abi::{FnAbi, FnAbiLlvmExt};
|
||||||
use crate::common::AsCCharPtr;
|
use crate::common::AsCCharPtr;
|
||||||
use crate::context::CodegenCx;
|
use crate::context::{CodegenCx, 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;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::{attributes, llvm};
|
use crate::{attributes, llvm};
|
||||||
|
|
||||||
/// Declare a function.
|
/// Declare a function with a SimpleCx.
|
||||||
///
|
///
|
||||||
/// 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
|
||||||
/// update the declaration and return existing Value instead.
|
/// update the declaration and return existing Value instead.
|
||||||
pub(crate) fn declare_raw_fn<'ll>(
|
pub(crate) fn declare_simple_fn<'ll>(
|
||||||
cx: &CodegenCx<'ll, '_>,
|
cx: &SimpleCx<'ll>,
|
||||||
name: &str,
|
name: &str,
|
||||||
callconv: llvm::CallConv,
|
callconv: llvm::CallConv,
|
||||||
unnamed: llvm::UnnamedAddr,
|
unnamed: llvm::UnnamedAddr,
|
||||||
visibility: llvm::Visibility,
|
visibility: llvm::Visibility,
|
||||||
ty: &'ll Type,
|
ty: &'ll Type,
|
||||||
) -> &'ll Value {
|
) -> &'ll Value {
|
||||||
debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
|
debug!("declare_simple_fn(name={:?}, ty={:?})", name, ty);
|
||||||
let llfn = unsafe {
|
let llfn = unsafe {
|
||||||
llvm::LLVMRustGetOrInsertFunction(cx.llmod, name.as_c_char_ptr(), name.len(), ty)
|
llvm::LLVMRustGetOrInsertFunction(cx.llmod, name.as_c_char_ptr(), name.len(), ty)
|
||||||
};
|
};
|
||||||
|
@ -49,6 +49,24 @@ pub(crate) fn declare_raw_fn<'ll>(
|
||||||
llvm::SetUnnamedAddress(llfn, unnamed);
|
llvm::SetUnnamedAddress(llfn, unnamed);
|
||||||
llvm::set_visibility(llfn, visibility);
|
llvm::set_visibility(llfn, visibility);
|
||||||
|
|
||||||
|
llfn
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Declare a function.
|
||||||
|
///
|
||||||
|
/// If there’s a value with the same name already declared, the function will
|
||||||
|
/// update the declaration and return existing Value instead.
|
||||||
|
pub(crate) fn declare_raw_fn<'ll, 'tcx>(
|
||||||
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
|
name: &str,
|
||||||
|
callconv: llvm::CallConv,
|
||||||
|
unnamed: llvm::UnnamedAddr,
|
||||||
|
visibility: llvm::Visibility,
|
||||||
|
ty: &'ll Type,
|
||||||
|
) -> &'ll Value {
|
||||||
|
debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
|
||||||
|
let llfn = declare_simple_fn(cx, name, callconv, unnamed, visibility, ty);
|
||||||
|
|
||||||
let mut attrs = SmallVec::<[_; 4]>::new();
|
let mut attrs = SmallVec::<[_; 4]>::new();
|
||||||
|
|
||||||
if cx.tcx.sess.opts.cg.no_redzone.unwrap_or(cx.tcx.sess.target.disable_redzone) {
|
if cx.tcx.sess.opts.cg.no_redzone.unwrap_or(cx.tcx.sess.target.disable_redzone) {
|
||||||
|
|
|
@ -1081,11 +1081,11 @@ fn codegen_emcc_try<'ll>(
|
||||||
|
|
||||||
// Helper function to give a Block to a closure to codegen a shim function.
|
// Helper function to give a Block to a closure to codegen a shim function.
|
||||||
// This is currently primarily used for the `try` intrinsic functions above.
|
// This is currently primarily used for the `try` intrinsic functions above.
|
||||||
fn gen_fn<'ll, 'tcx>(
|
fn gen_fn<'a, 'll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &'a CodegenCx<'ll, 'tcx>,
|
||||||
name: &str,
|
name: &str,
|
||||||
rust_fn_sig: ty::PolyFnSig<'tcx>,
|
rust_fn_sig: ty::PolyFnSig<'tcx>,
|
||||||
codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>),
|
codegen: &mut dyn FnMut(Builder<'a, 'll, 'tcx>),
|
||||||
) -> (&'ll Type, &'ll Value) {
|
) -> (&'ll Type, &'ll Value) {
|
||||||
let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty());
|
let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty());
|
||||||
let llty = fn_abi.llvm_type(cx);
|
let llty = fn_abi.llvm_type(cx);
|
||||||
|
@ -1104,9 +1104,9 @@ fn gen_fn<'ll, 'tcx>(
|
||||||
// catch exceptions.
|
// catch exceptions.
|
||||||
//
|
//
|
||||||
// This function is only generated once and is then cached.
|
// This function is only generated once and is then cached.
|
||||||
fn get_rust_try_fn<'ll, 'tcx>(
|
fn get_rust_try_fn<'a, 'll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &'a CodegenCx<'ll, 'tcx>,
|
||||||
codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>),
|
codegen: &mut dyn FnMut(Builder<'a, 'll, 'tcx>),
|
||||||
) -> (&'ll Type, &'ll Value) {
|
) -> (&'ll Type, &'ll Value) {
|
||||||
if let Some(llfn) = cx.rust_try_fn.get() {
|
if let Some(llfn) = cx.rust_try_fn.get() {
|
||||||
return llfn;
|
return llfn;
|
||||||
|
|
|
@ -237,7 +237,6 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
||||||
/// Generate autodiff rules
|
/// Generate autodiff rules
|
||||||
fn autodiff(
|
fn autodiff(
|
||||||
cgcx: &CodegenContext<Self>,
|
cgcx: &CodegenContext<Self>,
|
||||||
tcx: TyCtxt<'_>,
|
|
||||||
module: &ModuleCodegen<Self::Module>,
|
module: &ModuleCodegen<Self::Module>,
|
||||||
diff_fncs: Vec<AutoDiffItem>,
|
diff_fncs: Vec<AutoDiffItem>,
|
||||||
config: &ModuleConfig,
|
config: &ModuleConfig,
|
||||||
|
@ -246,7 +245,7 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
||||||
let dcx = cgcx.create_dcx();
|
let dcx = cgcx.create_dcx();
|
||||||
return Err(dcx.handle().emit_almost_fatal(AutoDiffWithoutLTO));
|
return Err(dcx.handle().emit_almost_fatal(AutoDiffWithoutLTO));
|
||||||
}
|
}
|
||||||
builder::autodiff::differentiate(module, cgcx, tcx, diff_fncs, config)
|
builder::autodiff::differentiate(module, cgcx, diff_fncs, config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use rustc_middle::ty::{self, Ty};
|
||||||
use rustc_target::callconv::{CastTarget, FnAbi, Reg};
|
use rustc_target::callconv::{CastTarget, FnAbi, Reg};
|
||||||
|
|
||||||
use crate::abi::{FnAbiLlvmExt, LlvmType};
|
use crate::abi::{FnAbiLlvmExt, LlvmType};
|
||||||
use crate::context::CodegenCx;
|
use crate::context::{CodegenCx, SimpleCx};
|
||||||
pub(crate) use crate::llvm::Type;
|
pub(crate) use crate::llvm::Type;
|
||||||
use crate::llvm::{Bool, False, Metadata, True};
|
use crate::llvm::{Bool, False, Metadata, True};
|
||||||
use crate::type_of::LayoutLlvmExt;
|
use crate::type_of::LayoutLlvmExt;
|
||||||
|
@ -35,7 +35,8 @@ impl fmt::Debug for Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ll> CodegenCx<'ll, '_> {
|
impl<'ll> CodegenCx<'ll, '_> {}
|
||||||
|
impl<'ll> SimpleCx<'ll> {
|
||||||
pub(crate) fn type_named_struct(&self, name: &str) -> &'ll Type {
|
pub(crate) fn type_named_struct(&self, name: &str) -> &'ll Type {
|
||||||
let name = SmallCStr::new(name);
|
let name = SmallCStr::new(name);
|
||||||
unsafe { llvm::LLVMStructCreateNamed(self.llcx, name.as_ptr()) }
|
unsafe { llvm::LLVMStructCreateNamed(self.llcx, name.as_ptr()) }
|
||||||
|
@ -44,11 +45,9 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||||
pub(crate) fn set_struct_body(&self, ty: &'ll Type, els: &[&'ll Type], packed: bool) {
|
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) }
|
unsafe { llvm::LLVMStructSetBody(ty, els.as_ptr(), els.len() as c_uint, packed as Bool) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn type_void(&self) -> &'ll Type {
|
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 {
|
pub(crate) fn type_token(&self) -> &'ll Type {
|
||||||
unsafe { llvm::LLVMTokenTypeInContext(self.llcx) }
|
unsafe { llvm::LLVMTokenTypeInContext(self.llcx) }
|
||||||
}
|
}
|
||||||
|
@ -75,7 +74,8 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||||
args
|
args
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||||
pub(crate) fn type_bool(&self) -> &'ll Type {
|
pub(crate) fn type_bool(&self) -> &'ll Type {
|
||||||
self.type_i8()
|
self.type_i8()
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,8 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||||
assert_eq!(size % unit_size, 0);
|
assert_eq!(size % unit_size, 0);
|
||||||
self.type_array(self.type_from_integer(unit), size / unit_size)
|
self.type_array(self.type_from_integer(unit), size / unit_size)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
impl<'ll> SimpleCx<'ll> {
|
||||||
pub(crate) fn type_variadic_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
|
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) }
|
unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ use std::sync::Arc;
|
||||||
use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
|
use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
|
||||||
use rustc_data_structures::memmap::Mmap;
|
use rustc_data_structures::memmap::Mmap;
|
||||||
use rustc_errors::FatalError;
|
use rustc_errors::FatalError;
|
||||||
use rustc_middle::ty::TyCtxt;
|
|
||||||
|
|
||||||
use super::write::CodegenContext;
|
use super::write::CodegenContext;
|
||||||
use crate::ModuleCodegen;
|
use crate::ModuleCodegen;
|
||||||
|
@ -89,13 +88,12 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
|
||||||
pub unsafe fn autodiff(
|
pub unsafe fn autodiff(
|
||||||
self,
|
self,
|
||||||
cgcx: &CodegenContext<B>,
|
cgcx: &CodegenContext<B>,
|
||||||
tcx: TyCtxt<'_>,
|
|
||||||
diff_fncs: Vec<AutoDiffItem>,
|
diff_fncs: Vec<AutoDiffItem>,
|
||||||
config: &ModuleConfig,
|
config: &ModuleConfig,
|
||||||
) -> Result<LtoModuleCodegen<B>, FatalError> {
|
) -> Result<LtoModuleCodegen<B>, FatalError> {
|
||||||
match &self {
|
match &self {
|
||||||
LtoModuleCodegen::Fat(module) => {
|
LtoModuleCodegen::Fat(module) => {
|
||||||
B::autodiff(cgcx, tcx, &module, diff_fncs, config)?;
|
B::autodiff(cgcx, &module, diff_fncs, config)?;
|
||||||
}
|
}
|
||||||
_ => panic!("autodiff called with non-fat LTO module"),
|
_ => panic!("autodiff called with non-fat LTO module"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
|
use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
|
||||||
use rustc_errors::{DiagCtxtHandle, FatalError};
|
use rustc_errors::{DiagCtxtHandle, FatalError};
|
||||||
use rustc_middle::dep_graph::WorkProduct;
|
use rustc_middle::dep_graph::WorkProduct;
|
||||||
use rustc_middle::ty::TyCtxt;
|
|
||||||
|
|
||||||
use crate::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
|
use crate::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
|
||||||
use crate::back::write::{CodegenContext, FatLtoInput, ModuleConfig};
|
use crate::back::write::{CodegenContext, FatLtoInput, ModuleConfig};
|
||||||
|
@ -65,7 +64,6 @@ pub trait WriteBackendMethods: 'static + Sized + Clone {
|
||||||
fn serialize_module(module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer);
|
fn serialize_module(module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer);
|
||||||
fn autodiff(
|
fn autodiff(
|
||||||
cgcx: &CodegenContext<Self>,
|
cgcx: &CodegenContext<Self>,
|
||||||
tcx: TyCtxt<'_>,
|
|
||||||
module: &ModuleCodegen<Self::Module>,
|
module: &ModuleCodegen<Self::Module>,
|
||||||
diff_fncs: Vec<AutoDiffItem>,
|
diff_fncs: Vec<AutoDiffItem>,
|
||||||
config: &ModuleConfig,
|
config: &ModuleConfig,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue