Skip to content

Commit 879c4d5

Browse files
authored
Rollup merge of #132342 - Zalathar:operand-bundle, r=workingjubilee
cg_llvm: Clean up FFI calls for operand bundles All of these FFI functions have equivalents in the stable LLVM-C API, though `LLVMBuildCallBr` requires a temporary polyfill on LLVM 18. This PR also creates a clear split between `OperandBundleOwned` and `OperandBundle`, and updates the internals of the owner to be a little less terrifying.
2 parents cf2cc01 + c307159 commit 879c4d5

File tree

6 files changed

+103
-138
lines changed

6 files changed

+103
-138
lines changed

compiler/rustc_codegen_llvm/src/allocator.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,15 @@ fn create_wrapper_function(
154154
.enumerate()
155155
.map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
156156
.collect::<Vec<_>>();
157-
let ret = llvm::LLVMRustBuildCall(
157+
let ret = llvm::LLVMBuildCallWithOperandBundles(
158158
llbuilder,
159159
ty,
160160
callee,
161161
args.as_ptr(),
162162
args.len() as c_uint,
163163
[].as_ptr(),
164164
0 as c_uint,
165+
c"".as_ptr(),
165166
);
166167
llvm::LLVMSetTailCall(ret, True);
167168
if output.is_some() {

compiler/rustc_codegen_llvm/src/builder.rs

+9-14
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
239239

240240
let args = self.check_call("invoke", llty, llfn, args);
241241
let funclet_bundle = funclet.map(|funclet| funclet.bundle());
242-
let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
243242
let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
244243
if let Some(funclet_bundle) = funclet_bundle {
245244
bundles.push(funclet_bundle);
@@ -250,13 +249,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
250249

251250
// Emit KCFI operand bundle
252251
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
253-
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
254-
if let Some(kcfi_bundle) = kcfi_bundle {
252+
if let Some(kcfi_bundle) = kcfi_bundle.as_deref() {
255253
bundles.push(kcfi_bundle);
256254
}
257255

258256
let invoke = unsafe {
259-
llvm::LLVMRustBuildInvoke(
257+
llvm::LLVMBuildInvokeWithOperandBundles(
260258
self.llbuilder,
261259
llty,
262260
llfn,
@@ -1179,7 +1177,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
11791177

11801178
let args = self.check_call("call", llty, llfn, args);
11811179
let funclet_bundle = funclet.map(|funclet| funclet.bundle());
1182-
let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
11831180
let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
11841181
if let Some(funclet_bundle) = funclet_bundle {
11851182
bundles.push(funclet_bundle);
@@ -1190,20 +1187,20 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
11901187

11911188
// Emit KCFI operand bundle
11921189
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
1193-
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
1194-
if let Some(kcfi_bundle) = kcfi_bundle {
1190+
if let Some(kcfi_bundle) = kcfi_bundle.as_deref() {
11951191
bundles.push(kcfi_bundle);
11961192
}
11971193

11981194
let call = unsafe {
1199-
llvm::LLVMRustBuildCall(
1195+
llvm::LLVMBuildCallWithOperandBundles(
12001196
self.llbuilder,
12011197
llty,
12021198
llfn,
12031199
args.as_ptr() as *const &llvm::Value,
12041200
args.len() as c_uint,
12051201
bundles.as_ptr(),
12061202
bundles.len() as c_uint,
1203+
c"".as_ptr(),
12071204
)
12081205
};
12091206
if let Some(fn_abi) = fn_abi {
@@ -1509,7 +1506,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
15091506

15101507
let args = self.check_call("callbr", llty, llfn, args);
15111508
let funclet_bundle = funclet.map(|funclet| funclet.bundle());
1512-
let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
15131509
let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
15141510
if let Some(funclet_bundle) = funclet_bundle {
15151511
bundles.push(funclet_bundle);
@@ -1520,13 +1516,12 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
15201516

15211517
// Emit KCFI operand bundle
15221518
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
1523-
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
1524-
if let Some(kcfi_bundle) = kcfi_bundle {
1519+
if let Some(kcfi_bundle) = kcfi_bundle.as_deref() {
15251520
bundles.push(kcfi_bundle);
15261521
}
15271522

15281523
let callbr = unsafe {
1529-
llvm::LLVMRustBuildCallBr(
1524+
llvm::LLVMBuildCallBr(
15301525
self.llbuilder,
15311526
llty,
15321527
llfn,
@@ -1601,7 +1596,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
16011596
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
16021597
instance: Option<Instance<'tcx>>,
16031598
llfn: &'ll Value,
1604-
) -> Option<llvm::OperandBundleDef<'ll>> {
1599+
) -> Option<llvm::OperandBundleOwned<'ll>> {
16051600
let is_indirect_call = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) };
16061601
let kcfi_bundle = if self.tcx.sess.is_sanitizer_kcfi_enabled()
16071602
&& let Some(fn_abi) = fn_abi
@@ -1627,7 +1622,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
16271622
kcfi::typeid_for_fnabi(self.tcx, fn_abi, options)
16281623
};
16291624

1630-
Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
1625+
Some(llvm::OperandBundleOwned::new("kcfi", &[self.const_u32(kcfi_typeid)]))
16311626
} else {
16321627
None
16331628
};

compiler/rustc_codegen_llvm/src/common.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use tracing::debug;
1717

1818
use crate::consts::const_alloc_to_llvm;
1919
pub(crate) use crate::context::CodegenCx;
20-
use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, Metadata, OperandBundleDef, True};
20+
use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, Metadata, True};
2121
use crate::type_::Type;
2222
use crate::value::Value;
2323

@@ -63,19 +63,19 @@ use crate::value::Value;
6363
/// the `OperandBundleDef` value created for MSVC landing pads.
6464
pub(crate) struct Funclet<'ll> {
6565
cleanuppad: &'ll Value,
66-
operand: OperandBundleDef<'ll>,
66+
operand: llvm::OperandBundleOwned<'ll>,
6767
}
6868

6969
impl<'ll> Funclet<'ll> {
7070
pub(crate) fn new(cleanuppad: &'ll Value) -> Self {
71-
Funclet { cleanuppad, operand: OperandBundleDef::new("funclet", &[cleanuppad]) }
71+
Funclet { cleanuppad, operand: llvm::OperandBundleOwned::new("funclet", &[cleanuppad]) }
7272
}
7373

7474
pub(crate) fn cleanuppad(&self) -> &'ll Value {
7575
self.cleanuppad
7676
}
7777

78-
pub(crate) fn bundle(&self) -> &OperandBundleDef<'ll> {
78+
pub(crate) fn bundle(&self) -> &llvm::OperandBundle<'ll> {
7979
&self.operand
8080
}
8181
}

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+47-44
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
use std::fmt::Debug;
55
use std::marker::PhantomData;
6+
use std::ptr;
67

78
use libc::{c_char, c_int, c_uint, c_ulonglong, c_void, size_t};
89
use rustc_macros::TryFromU32;
@@ -708,8 +709,9 @@ unsafe extern "C" {
708709
}
709710
#[repr(C)]
710711
pub struct RustArchiveMember<'a>(InvariantOpaque<'a>);
712+
/// Opaque pointee of `LLVMOperandBundleRef`.
711713
#[repr(C)]
712-
pub struct OperandBundleDef<'a>(InvariantOpaque<'a>);
714+
pub(crate) struct OperandBundle<'a>(InvariantOpaque<'a>);
713715
#[repr(C)]
714716
pub struct Linker<'a>(InvariantOpaque<'a>);
715717

@@ -1538,6 +1540,50 @@ unsafe extern "C" {
15381540

15391541
pub fn LLVMGetOrInsertComdat(M: &Module, Name: *const c_char) -> &Comdat;
15401542
pub fn LLVMSetComdat(V: &Value, C: &Comdat);
1543+
1544+
pub(crate) fn LLVMCreateOperandBundle(
1545+
Tag: *const c_char,
1546+
TagLen: size_t,
1547+
Args: *const &'_ Value,
1548+
NumArgs: c_uint,
1549+
) -> *mut OperandBundle<'_>;
1550+
pub(crate) fn LLVMDisposeOperandBundle(Bundle: ptr::NonNull<OperandBundle<'_>>);
1551+
1552+
pub(crate) fn LLVMBuildCallWithOperandBundles<'a>(
1553+
B: &Builder<'a>,
1554+
Ty: &'a Type,
1555+
Fn: &'a Value,
1556+
Args: *const &'a Value,
1557+
NumArgs: c_uint,
1558+
Bundles: *const &OperandBundle<'a>,
1559+
NumBundles: c_uint,
1560+
Name: *const c_char,
1561+
) -> &'a Value;
1562+
pub(crate) fn LLVMBuildInvokeWithOperandBundles<'a>(
1563+
B: &Builder<'a>,
1564+
Ty: &'a Type,
1565+
Fn: &'a Value,
1566+
Args: *const &'a Value,
1567+
NumArgs: c_uint,
1568+
Then: &'a BasicBlock,
1569+
Catch: &'a BasicBlock,
1570+
Bundles: *const &OperandBundle<'a>,
1571+
NumBundles: c_uint,
1572+
Name: *const c_char,
1573+
) -> &'a Value;
1574+
pub(crate) fn LLVMBuildCallBr<'a>(
1575+
B: &Builder<'a>,
1576+
Ty: &'a Type,
1577+
Fn: &'a Value,
1578+
DefaultDest: &'a BasicBlock,
1579+
IndirectDests: *const &'a BasicBlock,
1580+
NumIndirectDests: c_uint,
1581+
Args: *const &'a Value,
1582+
NumArgs: c_uint,
1583+
Bundles: *const &OperandBundle<'a>,
1584+
NumBundles: c_uint,
1585+
Name: *const c_char,
1586+
) -> &'a Value;
15411587
}
15421588

15431589
#[link(name = "llvm-wrapper", kind = "static")]
@@ -1623,47 +1669,11 @@ unsafe extern "C" {
16231669
AttrsLen: size_t,
16241670
);
16251671

1626-
pub fn LLVMRustBuildInvoke<'a>(
1627-
B: &Builder<'a>,
1628-
Ty: &'a Type,
1629-
Fn: &'a Value,
1630-
Args: *const &'a Value,
1631-
NumArgs: c_uint,
1632-
Then: &'a BasicBlock,
1633-
Catch: &'a BasicBlock,
1634-
OpBundles: *const &OperandBundleDef<'a>,
1635-
NumOpBundles: c_uint,
1636-
Name: *const c_char,
1637-
) -> &'a Value;
1638-
1639-
pub fn LLVMRustBuildCallBr<'a>(
1640-
B: &Builder<'a>,
1641-
Ty: &'a Type,
1642-
Fn: &'a Value,
1643-
DefaultDest: &'a BasicBlock,
1644-
IndirectDests: *const &'a BasicBlock,
1645-
NumIndirectDests: c_uint,
1646-
Args: *const &'a Value,
1647-
NumArgs: c_uint,
1648-
OpBundles: *const &OperandBundleDef<'a>,
1649-
NumOpBundles: c_uint,
1650-
Name: *const c_char,
1651-
) -> &'a Value;
1652-
16531672
pub fn LLVMRustSetFastMath(Instr: &Value);
16541673
pub fn LLVMRustSetAlgebraicMath(Instr: &Value);
16551674
pub fn LLVMRustSetAllowReassoc(Instr: &Value);
16561675

16571676
// Miscellaneous instructions
1658-
pub fn LLVMRustBuildCall<'a>(
1659-
B: &Builder<'a>,
1660-
Ty: &'a Type,
1661-
Fn: &'a Value,
1662-
Args: *const &'a Value,
1663-
NumArgs: c_uint,
1664-
OpBundles: *const &OperandBundleDef<'a>,
1665-
NumOpBundles: c_uint,
1666-
) -> &'a Value;
16671677
pub fn LLVMRustBuildMemCpy<'a>(
16681678
B: &Builder<'a>,
16691679
Dst: &'a Value,
@@ -2357,13 +2367,6 @@ unsafe extern "C" {
23572367

23582368
pub fn LLVMRustSetDataLayoutFromTargetMachine<'a>(M: &'a Module, TM: &'a TargetMachine);
23592369

2360-
pub fn LLVMRustBuildOperandBundleDef(
2361-
Name: *const c_char,
2362-
Inputs: *const &'_ Value,
2363-
NumInputs: c_uint,
2364-
) -> &mut OperandBundleDef<'_>;
2365-
pub fn LLVMRustFreeOperandBundleDef<'a>(Bundle: &'a mut OperandBundleDef<'a>);
2366-
23672370
pub fn LLVMRustPositionBuilderAtStart<'a>(B: &Builder<'a>, BB: &'a BasicBlock);
23682371

23692372
pub fn LLVMRustSetModulePICLevel(M: &Module);

compiler/rustc_codegen_llvm/src/llvm/mod.rs

+27-11
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
use std::cell::RefCell;
44
use std::ffi::{CStr, CString};
5+
use std::ops::Deref;
6+
use std::ptr;
57
use std::str::FromStr;
68
use std::string::FromUtf8Error;
79

810
use libc::c_uint;
9-
use rustc_data_structures::small_c_str::SmallCStr;
1011
use rustc_llvm::RustString;
1112
use rustc_target::abi::{Align, Size, WrappingRange};
1213

@@ -331,28 +332,43 @@ pub fn last_error() -> Option<String> {
331332
}
332333
}
333334

334-
pub struct OperandBundleDef<'a> {
335-
pub raw: &'a mut ffi::OperandBundleDef<'a>,
335+
/// Owns an [`OperandBundle`], and will dispose of it when dropped.
336+
pub(crate) struct OperandBundleOwned<'a> {
337+
raw: ptr::NonNull<OperandBundle<'a>>,
336338
}
337339

338-
impl<'a> OperandBundleDef<'a> {
339-
pub fn new(name: &str, vals: &[&'a Value]) -> Self {
340-
let name = SmallCStr::new(name);
341-
let def = unsafe {
342-
LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint)
340+
impl<'a> OperandBundleOwned<'a> {
341+
pub(crate) fn new(name: &str, vals: &[&'a Value]) -> Self {
342+
let raw = unsafe {
343+
LLVMCreateOperandBundle(
344+
name.as_c_char_ptr(),
345+
name.len(),
346+
vals.as_ptr(),
347+
vals.len() as c_uint,
348+
)
343349
};
344-
OperandBundleDef { raw: def }
350+
OperandBundleOwned { raw: ptr::NonNull::new(raw).unwrap() }
345351
}
346352
}
347353

348-
impl Drop for OperandBundleDef<'_> {
354+
impl Drop for OperandBundleOwned<'_> {
349355
fn drop(&mut self) {
350356
unsafe {
351-
LLVMRustFreeOperandBundleDef(&mut *(self.raw as *mut _));
357+
LLVMDisposeOperandBundle(self.raw);
352358
}
353359
}
354360
}
355361

362+
impl<'a> Deref for OperandBundleOwned<'a> {
363+
type Target = OperandBundle<'a>;
364+
365+
fn deref(&self) -> &Self::Target {
366+
// SAFETY: The returned reference is opaque and can only used for FFI.
367+
// It is valid for as long as `&self` is.
368+
unsafe { self.raw.as_ref() }
369+
}
370+
}
371+
356372
pub(crate) fn add_module_flag_u32(
357373
module: &Module,
358374
merge_behavior: ModuleFlagMergeBehavior,

0 commit comments

Comments
 (0)