Avoid some duplication between SimpleCx and CodegenCx

This commit is contained in:
Oli Scherer 2025-02-24 08:15:31 +00:00
parent d4379d2afd
commit bfd88cead0
4 changed files with 96 additions and 90 deletions

View File

@ -30,7 +30,7 @@ use tracing::{debug, instrument};
use crate::abi::FnAbiLlvmExt; use crate::abi::FnAbiLlvmExt;
use crate::common::Funclet; use crate::common::Funclet;
use crate::context::{CodegenCx, SimpleCx}; use crate::context::{CodegenCx, FullCx, GenericCx, SCx};
use crate::llvm::{ use crate::llvm::{
self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, GEPNoWrapFlags, Metadata, True, self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, GEPNoWrapFlags, Metadata, True,
}; };
@ -40,15 +40,15 @@ use crate::value::Value;
use crate::{attributes, llvm_util}; use crate::{attributes, llvm_util};
#[must_use] #[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 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 SBuilder<'a, 'll> = GenericBuilder<'a, 'll, SCx<'ll>>;
pub(crate) type Builder<'a, 'll, 'tcx> = GenericBuilder<'a, 'll, CodegenCx<'ll, 'tcx>>; 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) { fn drop(&mut self) {
unsafe { unsafe {
llvm::LLVMDisposeBuilder(&mut *(self.llbuilder as *mut _)); llvm::LLVMDisposeBuilder(&mut *(self.llbuilder as *mut _));
@ -87,14 +87,15 @@ impl<'a, 'll> SBuilder<'a, 'll> {
}; };
call call
} }
}
fn with_scx(scx: &'a SimpleCx<'ll>) -> Self { 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. // Create a fresh builder from the simple context.
let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(scx.llcx) }; let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(scx.deref().borrow().llcx) };
SBuilder { llbuilder, cx: scx } GenericBuilder { 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 { pub(crate) fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe { llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, UNNAMED) } unsafe { llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, UNNAMED) }
} }
@ -108,16 +109,17 @@ impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> {
llvm::LLVMBuildRet(self.llbuilder, v); llvm::LLVMBuildRet(self.llbuilder, v);
} }
} }
}
impl<'a, 'll> SBuilder<'a, 'll> { fn build(cx: &'a GenericCx<'ll, CX>, llbb: &'ll BasicBlock) -> Self {
fn build(cx: &'a SimpleCx<'ll>, llbb: &'ll BasicBlock) -> SBuilder<'a, 'll> { let bx = Self::with_cx(cx);
let bx = SBuilder::with_scx(cx);
unsafe { unsafe {
llvm::LLVMPositionBuilderAtEnd(bx.llbuilder, llbb); llvm::LLVMPositionBuilderAtEnd(bx.llbuilder, llbb);
} }
bx bx
} }
}
impl<'a, 'll> SBuilder<'a, 'll> {
fn check_call<'b>( fn check_call<'b>(
&mut self, &mut self,
typ: &str, typ: &str,
@ -1472,26 +1474,12 @@ 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 {
// 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 { 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> { impl<'a, 'll, CX: Borrow<SCx<'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);
@ -1521,7 +1509,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 { 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) }
} }
@ -1666,7 +1654,7 @@ 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> { impl<'a, 'll, CX: Borrow<SCx<'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) }
} }
@ -1690,7 +1678,7 @@ 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> { impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
pub(crate) fn phi( pub(crate) fn phi(
&mut self, &mut self,
ty: &'ll Type, ty: &'ll Type,

View File

@ -286,7 +286,7 @@ pub(crate) fn differentiate<'ll>(
} }
let diag_handler = cgcx.create_dcx(); 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);
// First of all, did the user try to use autodiff without using the -Zautodiff=Enable flag? // First of all, did the user try to use autodiff without using the -Zautodiff=Enable flag?
if !diff_items.is_empty() if !diff_items.is_empty()

View File

@ -1,6 +1,7 @@
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::marker::PhantomData;
use std::ops::Deref; use std::ops::Deref;
use std::str; use std::str;
@ -43,18 +44,18 @@ 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 /// 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 /// other compiler pieces. Here we define a small subset which has enough information and can be
/// moved around more freely. /// moved around more freely.
pub(crate) struct SimpleCx<'ll> { pub(crate) struct SCx<'ll> {
pub llmod: &'ll llvm::Module, pub llmod: &'ll llvm::Module,
pub llcx: &'ll llvm::Context, pub llcx: &'ll llvm::Context,
} }
impl<'ll> Borrow<SimpleCx<'ll>> for CodegenCx<'ll, '_> { impl<'ll> Borrow<SCx<'ll>> for FullCx<'ll, '_> {
fn borrow(&self) -> &SimpleCx<'ll> { fn borrow(&self) -> &SCx<'ll> {
&self.scx &self.scx
} }
} }
impl<'ll, 'tcx> Deref for CodegenCx<'ll, 'tcx> { impl<'ll, 'tcx> Deref for FullCx<'ll, 'tcx> {
type Target = SimpleCx<'ll>; type Target = SimpleCx<'ll>;
#[inline] #[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 /// 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) type CodegenCx<'ll, 'tcx> = GenericCx<'ll, FullCx<'ll, 'tcx>>;
pub(crate) struct FullCx<'ll, 'tcx> {
pub tcx: TyCtxt<'tcx>, pub tcx: TyCtxt<'tcx>,
pub scx: SimpleCx<'ll>, pub scx: SimpleCx<'ll>,
pub use_dll_storage_attrs: bool, pub use_dll_storage_attrs: bool,
@ -581,9 +597,10 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
let isize_ty = Type::ix_llcx(llcx, tcx.data_layout.pointer_size.bits()); let isize_ty = Type::ix_llcx(llcx, tcx.data_layout.pointer_size.bits());
CodegenCx { GenericCx(
FullCx {
tcx, tcx,
scx: SimpleCx { llcx, llmod }, scx: SimpleCx::new(llmod, llcx),
use_dll_storage_attrs, use_dll_storage_attrs,
tls_model, tls_model,
codegen_unit, codegen_unit,
@ -605,7 +622,9 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
intrinsics: Default::default(), intrinsics: Default::default(),
local_gen_sym_counter: Cell::new(0), local_gen_sym_counter: Cell::new(0),
renamed_statics: Default::default(), renamed_statics: Default::default(),
} },
PhantomData,
)
} }
pub(crate) fn statics_to_rauw(&self) -> &RefCell<Vec<(&'ll Value, &'ll Value)>> { pub(crate) fn statics_to_rauw(&self) -> &RefCell<Vec<(&'ll Value, &'ll Value)>> {
@ -628,7 +647,12 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
llvm::set_section(g, c"llvm.metadata"); llvm::set_section(g, c"llvm.metadata");
} }
} }
impl<'ll> SimpleCx<'ll> { impl<'ll> SimpleCx<'ll> {
pub(crate) fn new(llmod: &'ll llvm::Module, llcx: &'ll llvm::Context) -> Self {
Self(SCx { llmod, llcx }, PhantomData)
}
pub(crate) fn val_ty(&self, v: &'ll Value) -> &'ll Type { pub(crate) fn val_ty(&self, v: &'ll Value) -> &'ll Type {
common::val_ty(v) common::val_ty(v)
} }
@ -1203,25 +1227,13 @@ impl CodegenCx<'_, '_> {
name.push_str(&(idx as u64).to_base(ALPHANUMERIC_ONLY)); name.push_str(&(idx as u64).to_base(ALPHANUMERIC_ONLY));
name name
} }
}
impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
/// A wrapper for [`llvm::LLVMSetMetadata`], but it takes `Metadata` as a parameter instead of `Value`. /// 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) { pub(crate) fn set_metadata<'a>(&self, val: &'a Value, kind_id: MetadataType, md: &'a Metadata) {
unsafe { unsafe {
let node = llvm::LLVMMetadataAsValue(&self.llcx, md); 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)]
/// 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); llvm::LLVMSetMetadata(val, kind_id as c_uint, node);
} }
} }

View File

@ -1,3 +1,4 @@
use std::borrow::Borrow;
use std::{fmt, ptr}; use std::{fmt, ptr};
use libc::{c_char, c_uint}; use libc::{c_char, c_uint};
@ -11,7 +12,7 @@ use rustc_middle::ty::{self, Ty};
use rustc_target::callconv::{CastTarget, FnAbi}; use rustc_target::callconv::{CastTarget, FnAbi};
use crate::abi::{FnAbiLlvmExt, LlvmType}; use crate::abi::{FnAbiLlvmExt, LlvmType};
use crate::context::{CodegenCx, SimpleCx}; use crate::context::{CodegenCx, GenericCx, SCx};
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;
@ -36,29 +37,29 @@ impl fmt::Debug for Type {
} }
impl<'ll> CodegenCx<'ll, '_> {} 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 { 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()) }
} }
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()) }
} }
pub(crate) fn type_metadata(&self) -> &'ll Type { 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 ///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 { 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 { pub(crate) fn type_vector(&self, ty: &'ll Type, len: u64) -> &'ll Type {
@ -121,19 +122,24 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
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> {
impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
pub(crate) fn llcx(&self) -> &'ll llvm::Context {
(**self).borrow().llcx
}
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) }
} }
pub(crate) fn type_i1(&self) -> &'ll Type { 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 { pub(crate) fn type_struct(&self, els: &[&'ll Type], packed: bool) -> &'ll Type {
unsafe { unsafe {
llvm::LLVMStructTypeInContext( llvm::LLVMStructTypeInContext(
self.llcx, self.llcx(),
els.as_ptr(), els.as_ptr(),
els.len() as c_uint, els.len() as c_uint,
packed as Bool, packed as Bool,