Skip to content

Clean up various LLVM FFI things in codegen_llvm #137549

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Mar 7, 2025
Merged
Prev Previous commit
Next Next commit
Avoid some duplication between SimpleCx and CodegenCx
  • Loading branch information
oli-obk committed Feb 24, 2025
commit bfd88cead0dd79717f123ad7e9a26ecad88653cb
54 changes: 21 additions & 33 deletions compiler/rustc_codegen_llvm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand All @@ -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 _));
Expand Down Expand Up @@ -87,14 +87,15 @@ impl<'a, 'll> SBuilder<'a, 'll> {
};
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.
let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(scx.llcx) };
SBuilder { llbuilder, cx: scx }
let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(scx.deref().borrow().llcx) };
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 {
unsafe { llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, UNNAMED) }
}
Expand All @@ -108,16 +109,17 @@ impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> {
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);

fn build(cx: &'a GenericCx<'ll, CX>, llbb: &'ll BasicBlock) -> Self {
let bx = Self::with_cx(cx);
unsafe {
llvm::LLVMPositionBuilderAtEnd(bx.llbuilder, llbb);
}
bx
}
}

impl<'a, 'll> SBuilder<'a, 'll> {
fn check_call<'b>(
&mut self,
typ: &str,
Expand Down Expand Up @@ -1472,26 +1474,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);
Expand Down Expand Up @@ -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 {
unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
}
Expand Down Expand Up @@ -1666,7 +1654,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
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 {
unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED) }
}
Expand All @@ -1690,7 +1678,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,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/builder/autodiff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ 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);

// First of all, did the user try to use autodiff without using the -Zautodiff=Enable flag?
if !diff_items.is_empty()
Expand Down
100 changes: 56 additions & 44 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
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;

Expand Down Expand Up @@ -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
/// 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,
}

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]
Expand All @@ -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,
Expand Down Expand Up @@ -581,31 +597,34 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {

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),
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(),
},
PhantomData,
)
}

pub(crate) fn statics_to_rauw(&self) -> &RefCell<Vec<(&'ll Value, &'ll Value)>> {
Expand All @@ -628,7 +647,12 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
llvm::set_section(g, c"llvm.metadata");
}
}

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 {
common::val_ty(v)
}
Expand Down Expand Up @@ -1203,25 +1227,13 @@ 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);
let node = llvm::LLVMMetadataAsValue(self.llcx(), md);
llvm::LLVMSetMetadata(val, kind_id as c_uint, node);
}
}
Expand Down
26 changes: 16 additions & 10 deletions compiler/rustc_codegen_llvm/src/type_.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::borrow::Borrow;
use std::{fmt, ptr};

use libc::{c_char, c_uint};
Expand All @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -121,19 +122,24 @@ 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 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,
Expand Down