Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 1 addition & 19 deletions compiler/rustc_codegen_llvm/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use std::borrow::Borrow;

use libc::{c_char, c_uint};
use libc::c_uint;
use rustc_abi::Primitive::Pointer;
use rustc_abi::{self as abi, ExternAbi, HasDataLayout as _};
use rustc_ast::Mutability;
Expand Down Expand Up @@ -511,21 +511,3 @@ pub(crate) fn get_dllimport<'tcx>(
tcx.native_library(id)
.and_then(|lib| lib.dll_imports.iter().find(|di| di.name.as_str() == name))
}

/// Extension trait for explicit casts to `*const c_char`.
pub(crate) trait AsCCharPtr {
/// Equivalent to `self.as_ptr().cast()`, but only casts to `*const c_char`.
fn as_c_char_ptr(&self) -> *const c_char;
}

impl AsCCharPtr for str {
fn as_c_char_ptr(&self) -> *const c_char {
self.as_ptr().cast()
}
}

impl AsCCharPtr for [u8] {
fn as_c_char_ptr(&self) -> *const c_char {
self.as_ptr().cast()
}
}
10 changes: 7 additions & 3 deletions compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![expect(dead_code)]

use libc::{c_char, c_uint};
use libc::{c_char, c_uchar, c_uint};

use super::MetadataKindId;
use super::ffi::{AttributeKind, BasicBlock, Context, Metadata, Module, Type, Value};
Expand Down Expand Up @@ -47,10 +47,14 @@ unsafe extern "C" {
pub(crate) fn LLVMRustGetArrayNumElements(Ty: &Type) -> u64;
pub(crate) fn LLVMRustHasFnAttribute(
F: &Value,
Name: *const c_char,
Name: *const c_uchar, // See "PTR_LEN_STR".
NameLen: libc::size_t,
) -> bool;
pub(crate) fn LLVMRustRemoveFnAttribute(F: &Value, Name: *const c_char, NameLen: libc::size_t);
pub(crate) fn LLVMRustRemoveFnAttribute(
F: &Value,
Name: *const c_uchar, // See "PTR_LEN_STR".
NameLen: libc::size_t,
);
pub(crate) fn LLVMGetFirstFunction(M: &Module) -> Option<&Value>;
pub(crate) fn LLVMGetNextFunction(Fn: &Value) -> Option<&Value>;
pub(crate) fn LLVMRustRemoveEnumAttributeAtIndex(
Expand Down
23 changes: 15 additions & 8 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -982,7 +982,11 @@ unsafe extern "C" {
// Operations on all values
pub(crate) fn LLVMTypeOf(Val: &Value) -> &Type;
pub(crate) fn LLVMGetValueName2(Val: &Value, Length: *mut size_t) -> *const c_char;
pub(crate) fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t);
pub(crate) fn LLVMSetValueName2(
Val: &Value,
Name: *const c_uchar, // See "PTR_LEN_STR".
NameLen: size_t,
);
pub(crate) fn LLVMReplaceAllUsesWith<'a>(OldVal: &'a Value, NewVal: &'a Value);
pub(crate) safe fn LLVMGetMetadata<'a>(
Val: &'a Value,
Expand Down Expand Up @@ -1117,9 +1121,9 @@ unsafe extern "C" {
// Operations on attributes
pub(crate) fn LLVMCreateStringAttribute(
C: &Context,
Name: *const c_char,
Name: *const c_uchar, // See "PTR_LEN_STR".
NameLen: c_uint,
Value: *const c_char,
Value: *const c_uchar, // See "PTR_LEN_STR".
ValueLen: c_uint,
) -> &Attribute;

Expand All @@ -1139,7 +1143,10 @@ unsafe extern "C" {
) -> &'a Value;

// Operations about llvm intrinsics
pub(crate) fn LLVMLookupIntrinsicID(Name: *const c_char, NameLen: size_t) -> c_uint;
pub(crate) fn LLVMLookupIntrinsicID(
Name: *const c_uchar, // See "PTR_LEN_STR".
NameLen: size_t,
) -> c_uint;
pub(crate) fn LLVMIntrinsicIsOverloaded(ID: NonZero<c_uint>) -> Bool;
pub(crate) fn LLVMGetIntrinsicDeclaration<'a>(
Mod: &'a Module,
Expand Down Expand Up @@ -1675,7 +1682,7 @@ unsafe extern "C" {
pub(crate) fn LLVMSetComdat(V: &Value, C: &Comdat);

pub(crate) fn LLVMCreateOperandBundle(
Tag: *const c_char,
Tag: *const c_uchar, // See "PTR_LEN_STR".
TagLen: size_t,
Args: *const &'_ Value,
NumArgs: c_uint,
Expand Down Expand Up @@ -2186,17 +2193,17 @@ unsafe extern "C" {
pub(crate) fn LLVMRustAddModuleFlagU32(
M: &Module,
MergeBehavior: ModuleFlagMergeBehavior,
Name: *const c_char,
Name: *const c_uchar, // See "PTR_LEN_STR".
NameLen: size_t,
Value: u32,
);

pub(crate) fn LLVMRustAddModuleFlagString(
M: &Module,
MergeBehavior: ModuleFlagMergeBehavior,
Name: *const c_char,
Name: *const c_uchar, // See "PTR_LEN_STR".
NameLen: size_t,
Value: *const c_char,
Value: *const c_uchar, // See "PTR_LEN_STR".
ValueLen: size_t,
);

Expand Down
41 changes: 17 additions & 24 deletions compiler/rustc_codegen_llvm/src/llvm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ pub(crate) use self::CodeGenOptSize::*;
pub(crate) use self::conversions::*;
pub(crate) use self::ffi::*;
pub(crate) use self::metadata_kind::*;
use crate::common::AsCCharPtr;

mod conversions;
pub(crate) mod diagnostic;
Expand Down Expand Up @@ -46,11 +45,11 @@ pub(crate) fn AddFunctionAttributes<'ll>(
}

pub(crate) fn HasStringAttribute<'ll>(llfn: &'ll Value, name: &str) -> bool {
unsafe { LLVMRustHasFnAttribute(llfn, name.as_c_char_ptr(), name.len()) }
unsafe { LLVMRustHasFnAttribute(llfn, name.as_ptr(), name.len()) }
}

pub(crate) fn RemoveStringAttrFromFn<'ll>(llfn: &'ll Value, name: &str) {
unsafe { LLVMRustRemoveFnAttribute(llfn, name.as_c_char_ptr(), name.len()) }
unsafe { LLVMRustRemoveFnAttribute(llfn, name.as_ptr(), name.len()) }
}

pub(crate) fn AddCallSiteAttributes<'ll>(
Expand All @@ -71,9 +70,9 @@ pub(crate) fn CreateAttrStringValue<'ll>(
unsafe {
LLVMCreateStringAttribute(
llcx,
attr.as_c_char_ptr(),
attr.as_ptr(),
attr.len().try_into().unwrap(),
value.as_c_char_ptr(),
value.as_ptr(),
value.len().try_into().unwrap(),
)
}
Expand All @@ -83,13 +82,15 @@ pub(crate) fn CreateAttrStringValueFromCStr<'ll>(
attr: &std::ffi::CStr,
value: &std::ffi::CStr,
) -> &'ll Attribute {
let attr = attr.to_bytes();
let value = value.to_bytes();
unsafe {
LLVMCreateStringAttribute(
llcx,
(*attr).as_ptr(),
(*attr).to_bytes().len() as c_uint,
(*value).as_ptr(),
(*value).to_bytes().len() as c_uint,
attr.as_ptr(),
attr.len() as c_uint,
value.as_ptr(),
value.len() as c_uint,
)
}
}
Expand All @@ -98,7 +99,7 @@ pub(crate) fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &str) -> &'ll Attr
unsafe {
LLVMCreateStringAttribute(
llcx,
attr.as_c_char_ptr(),
attr.as_ptr(),
attr.len().try_into().unwrap(),
std::ptr::null(),
0,
Expand Down Expand Up @@ -340,7 +341,7 @@ pub(crate) struct Intrinsic {

impl Intrinsic {
pub(crate) fn lookup(name: &[u8]) -> Option<Self> {
let id = unsafe { LLVMLookupIntrinsicID(name.as_c_char_ptr(), name.len()) };
let id = unsafe { LLVMLookupIntrinsicID(name.as_ptr(), name.len()) };
NonZero::new(id).map(|id| Self { id })
}

Expand All @@ -365,10 +366,7 @@ impl Intrinsic {

/// Safe wrapper for `LLVMSetValueName2` from a byte slice
pub(crate) fn set_value_name(value: &Value, name: &[u8]) {
unsafe {
let data = name.as_c_char_ptr();
LLVMSetValueName2(value, data, name.len());
}
unsafe { LLVMSetValueName2(value, name.as_ptr(), name.len()) };
}

pub(crate) fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
Expand Down Expand Up @@ -408,12 +406,7 @@ pub(crate) struct OperandBundleBox<'a> {
impl<'a> OperandBundleBox<'a> {
pub(crate) fn new(name: &str, vals: &[&'a Value]) -> Self {
let raw = unsafe {
LLVMCreateOperandBundle(
name.as_c_char_ptr(),
name.len(),
vals.as_ptr(),
vals.len() as c_uint,
)
LLVMCreateOperandBundle(name.as_ptr(), name.len(), vals.as_ptr(), vals.len() as c_uint)
};
Self { raw: ptr::NonNull::new(raw).unwrap() }
}
Expand Down Expand Up @@ -444,7 +437,7 @@ pub(crate) fn add_module_flag_u32(
value: u32,
) {
unsafe {
LLVMRustAddModuleFlagU32(module, merge_behavior, key.as_c_char_ptr(), key.len(), value);
LLVMRustAddModuleFlagU32(module, merge_behavior, key.as_ptr(), key.len(), value);
}
}

Expand All @@ -458,9 +451,9 @@ pub(crate) fn add_module_flag_str(
LLVMRustAddModuleFlagString(
module,
merge_behavior,
key.as_c_char_ptr(),
key.as_ptr(),
key.len(),
value.as_c_char_ptr(),
value.as_ptr(),
value.len(),
);
}
Expand Down
36 changes: 30 additions & 6 deletions compiler/rustc_public/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,21 @@ pub enum PassMode {
},
}

/// Attributes of a function argument that affect its ABI.
///
/// Not all internal compiler attributes are exposed here, as some are
/// LLVM-specific optimization hints. The internal representation is kept
/// private so it can be expanded in the future.
/// Attributes of a function argument or return value.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
pub struct ArgAttributes {
pub(crate) regular: ArgAttributeFlags,
pub(crate) arg_ext: ArgExtension,
pub(crate) pointee_size: Size,
pub(crate) pointee_align: Option<Align>,
}

impl ArgAttributes {
/// Return the calling convention and optimization flags for this argument.
pub fn regular(&self) -> ArgAttributeFlags {
self.regular
}

/// Return how this argument should be extended when passed in a register.
///
/// Relevant for integer arguments smaller than the register width.
Expand All @@ -128,12 +130,34 @@ impl ArgAttributes {
self.pointee_align
}

/// Return the minimum dereferenceable size of the pointee, if known.
/// Return the minimum dereferenceable size of the pointee, if it is non-null,
/// at function entry (for arguments) or return (for return values).
///
/// This alone does not guarantee dereferenceability for the duration of the call.
pub fn pointee_size(&self) -> Size {
self.pointee_size
}
}

/// Calling convention and optimization flags for a function argument or return value.
///
/// The capture flags overlap: `captures_none` implies `captures_address`, which
/// implies `captures_read_only`.
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)]
pub struct ArgAttributeFlags {
pub captures_none: bool,
pub captures_address: bool,
pub captures_read_only: bool,
pub no_alias: bool,
pub non_null: bool,
pub read_only: bool,
pub in_reg: bool,
pub no_undef: bool,
pub writable: bool,
pub no_free: bool,
}

/// How a small integer argument should be extended to fill a register.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)]
pub enum ArgExtension {
Expand Down
21 changes: 17 additions & 4 deletions compiler/rustc_public/src/unstable/convert/stable/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ use rustc_target::callconv;

use crate::IndexedVal;
use crate::abi::{
AddressSpace, ArgAbi, ArgAttributes, ArgExtension, CallConvention, CastTarget, FieldsShape,
FloatLength, FnAbi, IndirectMode, IntegerLength, IntegerType, Layout, LayoutShape,
NumScalableVectors, PassMode, Primitive, Reg, RegKind, ReprFlags, ReprOptions, Scalar,
TagEncoding, TyAndLayout, Uniform, ValueRepr, VariantFields, VariantsShape, WrappingRange,
AddressSpace, ArgAbi, ArgAttributeFlags, ArgAttributes, ArgExtension, CallConvention,
CastTarget, FieldsShape, FloatLength, FnAbi, IndirectMode, IntegerLength, IntegerType, Layout,
LayoutShape, NumScalableVectors, PassMode, Primitive, Reg, RegKind, ReprFlags, ReprOptions,
Scalar, TagEncoding, TyAndLayout, Uniform, ValueRepr, VariantFields, VariantsShape,
WrappingRange,
};
use crate::compiler_interface::BridgeTys;
use crate::target::MachineSize as Size;
Expand Down Expand Up @@ -264,6 +265,18 @@ impl<'tcx> Stable<'tcx> for callconv::ArgAttributes {
_: &CompilerCtxt<'cx, BridgeTys>,
) -> Self::T {
ArgAttributes {
regular: ArgAttributeFlags {
captures_none: self.regular.contains(callconv::ArgAttribute::CapturesNone),
captures_address: self.regular.contains(callconv::ArgAttribute::CapturesAddress),
captures_read_only: self.regular.contains(callconv::ArgAttribute::CapturesReadOnly),
no_alias: self.regular.contains(callconv::ArgAttribute::NoAlias),
non_null: self.regular.contains(callconv::ArgAttribute::NonNull),
read_only: self.regular.contains(callconv::ArgAttribute::ReadOnly),
in_reg: self.regular.contains(callconv::ArgAttribute::InReg),
no_undef: self.regular.contains(callconv::ArgAttribute::NoUndef),
writable: self.regular.contains(callconv::ArgAttribute::Writable),
no_free: self.regular.contains(callconv::ArgAttribute::NoFree),
},
arg_ext: match self.arg_ext {
callconv::ArgExtension::None => ArgExtension::None,
callconv::ArgExtension::Zext => ArgExtension::Zext,
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_target/src/callconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,9 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
// Only integers have signedness
if let BackendRepr::Scalar(scalar) = self.layout.backend_repr
&& let Primitive::Int(i, signed) = scalar.primitive()
&& i.size().bits() < bits
// bools are i1 but their primitive is i8. Unlike other types,
// bools can be extended to their primitive size.
&& (i.size().bits() < bits || self.layout.backend_repr.is_bool())
&& let PassMode::Direct(ref mut attrs) = self.mode
{
if signed {
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_target/src/callconv/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,11 @@ where
} else if is_arg || cx.target_spec().is_like_darwin {
arg.extend_integer_width_to(32);
}
// The x86_64 psABI requires bools to be zero-extended to 8-bits, with high bits unspecified.
// zeroext i1 has this behavior in the LLVM X86 backend.
if !is_arg && arg.layout.backend_repr.is_bool() {
arg.extend_integer_width_to(8);
}
}
}
};
Expand Down
Loading
Loading