Rollup merge of #135581 - EnzymeAD:refactor-codgencx, r=oli-obk
Separate Builder methods from tcx As part of the autodiff upstreaming we noticed, that it would be nice to have various builder methods available without the TypeContext, which prevents the normal CodegenCx to be passed around between threads. We introduce a SimpleCx which just owns the llvm module and llvm context, to encapsulate them. The previous CodegenCx now implements deref and forwards access to the llvm module or context to it's SimpleCx sub-struct. This gives us a bit more flexibility, because now we can pass (or construct) the SimpleCx in locations where we don't have enough information to construct a CodegenCx, or are not able to pass it around due to the tcx lifetimes (and it not implementing send/sync). This also introduces an SBuilder, similar to the SimpleCx. The SBuilder uses a SimpleCx, whereas the existing Builder uses the larger CodegenCx. I will push updates to make implementations generic (where possible) to be implemented once and work for either of the two. I'll also clean up the leftover code. `call` is a bit tricky, because it requires a tcx, I probably need to duplicate it after all. Tracking: - https://github.com/rust-lang/rust/issues/124509
This commit is contained in:
commit
1e454fe725
10 changed files with 239 additions and 56 deletions
|
@ -1,4 +1,4 @@
|
|||
use std::borrow::Cow;
|
||||
use std::borrow::{Borrow, Cow};
|
||||
use std::ops::Deref;
|
||||
use std::{iter, ptr};
|
||||
|
||||
|
@ -31,20 +31,22 @@ use tracing::{debug, instrument};
|
|||
use crate::abi::FnAbiLlvmExt;
|
||||
use crate::attributes;
|
||||
use crate::common::Funclet;
|
||||
use crate::context::CodegenCx;
|
||||
use crate::context::{CodegenCx, SimpleCx};
|
||||
use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, True};
|
||||
use crate::type_::Type;
|
||||
use crate::type_of::LayoutLlvmExt;
|
||||
use crate::value::Value;
|
||||
|
||||
// All Builders must have an llfn associated with them
|
||||
#[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 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) {
|
||||
unsafe {
|
||||
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
|
||||
/// 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.
|
||||
|
@ -1222,6 +1330,14 @@ 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) };
|
||||
|
@ -1231,13 +1347,16 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
|||
pub(crate) fn llfn(&self) -> &'ll Value {
|
||||
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) {
|
||||
unsafe {
|
||||
llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||
fn align_metadata(&mut self, load: &'ll Value, align: Align) {
|
||||
unsafe {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
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 {
|
||||
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) };
|
||||
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,
|
||||
|
@ -1401,11 +1523,13 @@ 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);
|
||||
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]);
|
||||
}
|
||||
|
||||
}
|
||||
impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> {
|
||||
pub(crate) fn phi(
|
||||
&mut self,
|
||||
ty: &'ll Type,
|
||||
|
@ -1443,7 +1568,8 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
|||
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 {
|
||||
let src_ty = self.cx.val_ty(val);
|
||||
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_codegen_ssa::ModuleCodegen;
|
||||
use rustc_codegen_ssa::back::write::ModuleConfig;
|
||||
use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods};
|
||||
use rustc_errors::FatalError;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::Lto;
|
||||
use tracing::{debug, trace};
|
||||
|
||||
use crate::back::write::{llvm_err, llvm_optimize};
|
||||
use crate::builder::Builder;
|
||||
use crate::declare::declare_raw_fn;
|
||||
use crate::builder::SBuilder;
|
||||
use crate::context::SimpleCx;
|
||||
use crate::declare::declare_simple_fn;
|
||||
use crate::errors::LlvmError;
|
||||
use crate::llvm::AttributePlace::Function;
|
||||
use crate::llvm::{Metadata, True};
|
||||
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> {
|
||||
unsafe {
|
||||
|
@ -38,8 +37,8 @@ fn get_params(fnc: &Value) -> Vec<&Value> {
|
|||
/// [^1]: <https://enzyme.mit.edu/getting_started/CallingConvention/>
|
||||
// FIXME(ZuseZ4): `outer_fn` should include upstream safety checks to
|
||||
// cover some assumptions of enzyme/autodiff, which could lead to UB otherwise.
|
||||
fn generate_enzyme_call<'ll, 'tcx>(
|
||||
cx: &context::CodegenCx<'ll, 'tcx>,
|
||||
fn generate_enzyme_call<'ll>(
|
||||
cx: &SimpleCx<'ll>,
|
||||
fn_to_diff: &'ll Value,
|
||||
outer_fn: &'ll Value,
|
||||
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
|
||||
// think a bit more about what should go here.
|
||||
let cc = llvm::LLVMGetFunctionCallConv(outer_fn);
|
||||
let ad_fn = declare_raw_fn(
|
||||
let ad_fn = declare_simple_fn(
|
||||
cx,
|
||||
&ad_name,
|
||||
llvm::CallConv::try_from(cc).expect("invalid callconv"),
|
||||
|
@ -132,7 +131,7 @@ fn generate_enzyme_call<'ll, 'tcx>(
|
|||
llvm::LLVMRustEraseInstFromParent(br);
|
||||
|
||||
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 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
|
||||
// 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>,
|
||||
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
diff_items: Vec<AutoDiffItem>,
|
||||
config: &ModuleConfig,
|
||||
) -> Result<(), FatalError> {
|
||||
|
@ -286,8 +284,7 @@ pub(crate) fn differentiate<'ll, 'tcx>(
|
|||
}
|
||||
|
||||
let diag_handler = cgcx.create_dcx();
|
||||
let (_, cgus) = tcx.collect_and_partition_mono_items(());
|
||||
let cx = context::CodegenCx::new(tcx, &cgus.first().unwrap(), &module.module_llvm);
|
||||
let cx = SimpleCx { llmod: module.module_llvm.llmod(), llcx: module.module_llvm.llcx };
|
||||
|
||||
// Before dumping the module, we want all the TypeTrees to become part of the module.
|
||||
for item in diff_items.iter() {
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use std::borrow::Borrow;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::ffi::{CStr, c_char, c_uint};
|
||||
use std::ops::Deref;
|
||||
use std::str;
|
||||
|
||||
use rustc_abi::{HasDataLayout, 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};
|
||||
|
@ -30,23 +32,46 @@ use smallvec::SmallVec;
|
|||
|
||||
use crate::back::write::to_llvm_code_model;
|
||||
use crate::callee::get_fn;
|
||||
use crate::common::AsCCharPtr;
|
||||
use crate::common::{self, AsCCharPtr};
|
||||
use crate::debuginfo::metadata::apply_vcall_visibility_metadata;
|
||||
use crate::llvm::{Metadata, MetadataType};
|
||||
use crate::type_::Type;
|
||||
use crate::value::Value;
|
||||
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
|
||||
/// `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 tcx: TyCtxt<'tcx>,
|
||||
pub scx: SimpleCx<'ll>,
|
||||
pub use_dll_storage_attrs: bool,
|
||||
pub tls_model: llvm::ThreadLocalMode,
|
||||
|
||||
pub llmod: &'ll llvm::Module,
|
||||
pub llcx: &'ll llvm::Context,
|
||||
pub codegen_unit: &'tcx CodegenUnit<'tcx>,
|
||||
|
||||
/// Cache instances of monomorphic and polymorphic items
|
||||
|
@ -553,10 +578,9 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
|
||||
CodegenCx {
|
||||
tcx,
|
||||
scx: SimpleCx { llcx, llmod },
|
||||
use_dll_storage_attrs,
|
||||
tls_model,
|
||||
llmod,
|
||||
llcx,
|
||||
codegen_unit,
|
||||
instances: Default::default(),
|
||||
vtables: Default::default(),
|
||||
|
@ -600,6 +624,11 @@ 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)
|
||||
}
|
||||
|
||||
pub(crate) fn get_metadata_value(&self, metadata: &'ll Metadata) -> &'ll Value {
|
||||
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())
|
||||
})
|
||||
}
|
||||
|
||||
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> {
|
||||
|
@ -1178,6 +1211,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<'_, '_> {
|
||||
#[inline]
|
||||
fn data_layout(&self) -> &TargetDataLayout {
|
||||
|
|
|
@ -21,26 +21,26 @@ use tracing::debug;
|
|||
|
||||
use crate::abi::{FnAbi, FnAbiLlvmExt};
|
||||
use crate::common::AsCCharPtr;
|
||||
use crate::context::CodegenCx;
|
||||
use crate::context::{CodegenCx, SimpleCx};
|
||||
use crate::llvm::AttributePlace::Function;
|
||||
use crate::llvm::Visibility;
|
||||
use crate::type_::Type;
|
||||
use crate::value::Value;
|
||||
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
|
||||
/// update the declaration and return existing Value instead.
|
||||
pub(crate) fn declare_raw_fn<'ll>(
|
||||
cx: &CodegenCx<'ll, '_>,
|
||||
pub(crate) fn declare_simple_fn<'ll>(
|
||||
cx: &SimpleCx<'ll>,
|
||||
name: &str,
|
||||
callconv: llvm::CallConv,
|
||||
unnamed: llvm::UnnamedAddr,
|
||||
visibility: llvm::Visibility,
|
||||
ty: &'ll Type,
|
||||
) -> &'ll Value {
|
||||
debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
|
||||
debug!("declare_simple_fn(name={:?}, ty={:?})", name, ty);
|
||||
let llfn = unsafe {
|
||||
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::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();
|
||||
|
||||
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.
|
||||
// This is currently primarily used for the `try` intrinsic functions above.
|
||||
fn gen_fn<'ll, 'tcx>(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
fn gen_fn<'a, 'll, 'tcx>(
|
||||
cx: &'a CodegenCx<'ll, 'tcx>,
|
||||
name: &str,
|
||||
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) {
|
||||
let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty());
|
||||
let llty = fn_abi.llvm_type(cx);
|
||||
|
@ -1104,9 +1104,9 @@ fn gen_fn<'ll, 'tcx>(
|
|||
// catch exceptions.
|
||||
//
|
||||
// This function is only generated once and is then cached.
|
||||
fn get_rust_try_fn<'ll, 'tcx>(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>),
|
||||
fn get_rust_try_fn<'a, 'll, 'tcx>(
|
||||
cx: &'a CodegenCx<'ll, 'tcx>,
|
||||
codegen: &mut dyn FnMut(Builder<'a, 'll, 'tcx>),
|
||||
) -> (&'ll Type, &'ll Value) {
|
||||
if let Some(llfn) = cx.rust_try_fn.get() {
|
||||
return llfn;
|
||||
|
|
|
@ -237,7 +237,6 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
|||
/// Generate autodiff rules
|
||||
fn autodiff(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
tcx: TyCtxt<'_>,
|
||||
module: &ModuleCodegen<Self::Module>,
|
||||
diff_fncs: Vec<AutoDiffItem>,
|
||||
config: &ModuleConfig,
|
||||
|
@ -246,7 +245,7 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
|||
let dcx = cgcx.create_dcx();
|
||||
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 crate::abi::{FnAbiLlvmExt, LlvmType};
|
||||
use crate::context::CodegenCx;
|
||||
use crate::context::{CodegenCx, SimpleCx};
|
||||
pub(crate) use crate::llvm::Type;
|
||||
use crate::llvm::{Bool, False, Metadata, True};
|
||||
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 {
|
||||
let name = SmallCStr::new(name);
|
||||
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) {
|
||||
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) }
|
||||
}
|
||||
|
||||
pub(crate) fn type_token(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMTokenTypeInContext(self.llcx) }
|
||||
}
|
||||
|
@ -75,7 +74,8 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
args
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||
pub(crate) fn type_bool(&self) -> &'ll Type {
|
||||
self.type_i8()
|
||||
}
|
||||
|
@ -120,7 +120,8 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
assert_eq!(size % unit_size, 0);
|
||||
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 {
|
||||
unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) }
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue