Skip to content

Commit

Permalink
Add a scheme for moving away from extern "rust-intrinsic" entirely
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Feb 5, 2024
1 parent b9d8f00 commit 95d7abf
Show file tree
Hide file tree
Showing 28 changed files with 156 additions and 35 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1648,7 +1648,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {

let func_ty = func.ty(body, self.infcx.tcx);
if let ty::FnDef(def_id, _) = *func_ty.kind() {
if let Some(sym::simd_shuffle) = self.tcx().intrinsic(def_id) {
if self.tcx().is_intrinsic(def_id, sym::simd_shuffle) {
if !matches!(args[2], Spanned { node: Operand::Constant(_), .. }) {
self.tcx().dcx().emit_err(SimdShuffleLastConst { span: term.source_info.span });
}
Expand Down
12 changes: 11 additions & 1 deletion compiler/rustc_codegen_cranelift/src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,17 @@ pub(crate) fn codegen_terminator_call<'tcx>(
Ok(()) => return,
// Unimplemented intrinsics must have a fallback body. The fallback body is obtained
// by converting the `InstanceDef::Intrinsic` to an `InstanceDef::Item`.
Err(()) => Some(Instance::new(instance.def_id(), instance.args)),
Err(()) => {
let intrinsic = fx.tcx.intrinsic(instance.def_id()).unwrap();
if intrinsic.must_be_overridden {
span_bug!(
source_info.span,
"intrinsic {} must be overridden by codegen_cranelift, but isn't",
intrinsic.name,
);
}
Some(Instance::new(instance.def_id(), instance.args))
}
}
}
InstanceDef::DropGlue(_, None) => {
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/symbol_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use rustc_middle::ty::{self, SymbolName, TyCtxt};
use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
use rustc_middle::util::Providers;
use rustc_session::config::{CrateType, OomStrategy};
use rustc_span::sym;
use rustc_target::spec::{SanitizerSet, TlsModel};

pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
Expand Down Expand Up @@ -81,6 +82,10 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
return library.kind.is_statically_included().then_some(def_id);
}

if tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden) {
return None;
}

// Only consider nodes that actually have exported symbols.
match tcx.def_kind(def_id) {
DefKind::Fn | DefKind::Static(_) => {}
Expand Down
23 changes: 16 additions & 7 deletions compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, Instance, Ty};
use rustc_session::config::OptLevel;
use rustc_span::{source_map::Spanned, sym, Span, Symbol};
use rustc_span::{source_map::Spanned, sym, Span};
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg};
use rustc_target::abi::{self, HasDataLayout, WrappingRange};
use rustc_target::spec::abi::Abi;
Expand Down Expand Up @@ -672,7 +672,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
&mut self,
helper: &TerminatorCodegenHelper<'tcx>,
bx: &mut Bx,
intrinsic: Option<Symbol>,
intrinsic: Option<ty::IntrinsicDef>,
instance: Option<Instance<'tcx>>,
source_info: mir::SourceInfo,
target: Option<mir::BasicBlock>,
Expand All @@ -682,7 +682,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// Emit a panic or a no-op for `assert_*` intrinsics.
// These are intrinsics that compile to panics so that we can get a message
// which mentions the offending type, even from a const context.
let panic_intrinsic = intrinsic.and_then(|s| ValidityRequirement::from_intrinsic(s));
let panic_intrinsic = intrinsic.and_then(|i| ValidityRequirement::from_intrinsic(i.name));
if let Some(requirement) = panic_intrinsic {
let ty = instance.unwrap().args.type_at(0);

Expand Down Expand Up @@ -818,7 +818,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// The arguments we'll be passing. Plus one to account for outptr, if used.
let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize;

if intrinsic == Some(sym::caller_location) {
if matches!(intrinsic, Some(ty::IntrinsicDef { name: sym::caller_location, .. })) {
return if let Some(target) = target {
let location =
self.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info });
Expand All @@ -838,7 +838,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}

let instance = match intrinsic {
None | Some(sym::drop_in_place) => instance,
None | Some(ty::IntrinsicDef { name: sym::drop_in_place, .. }) => instance,
Some(intrinsic) => {
let mut llargs = Vec::with_capacity(1);
let ret_dest = self.make_return_dest(
Expand Down Expand Up @@ -866,7 +866,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// third argument must be constant. This is
// checked by const-qualification, which also
// promotes any complex rvalues to constants.
if i == 2 && intrinsic == sym::simd_shuffle {
if i == 2 && intrinsic.name == sym::simd_shuffle {
if let mir::Operand::Constant(constant) = &arg.node {
let (llval, ty) = self.simd_shuffle_indices(bx, constant);
return OperandRef {
Expand Down Expand Up @@ -897,7 +897,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
};
}
// Call the fallback body instead of generating the intrinsic code
Err(()) => Some(Instance::new(instance.def_id(), instance.args)),
Err(()) => {
if intrinsic.must_be_overridden {
span_bug!(
span,
"intrinsic {} must be overridden by codegen backend, but isn't",
intrinsic.name,
);
}
Some(Instance::new(instance.def_id(), instance.args))
}
}
}
};
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
rustc_intrinsic, Normal, template!(Word), ErrorFollowing,
"the `#[rustc_intrinsic]` attribute is used to declare intrinsics with function bodies",
),
rustc_attr!(
rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing,
"the `#[rustc_intrinsic_must_be_overridden]` attribute is used to declare intrinsics without real bodies",
),

// ==========================================================================
// Internal attributes, Testing:
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,12 +473,12 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
check_enum(tcx, def_id);
}
DefKind::Fn => {
if let Some(name) = tcx.intrinsic(def_id) {
if let Some(i) = tcx.intrinsic(def_id) {
intrinsic::check_intrinsic_type(
tcx,
def_id,
tcx.def_ident_span(def_id).unwrap(),
name,
i.name,
Abi::Rust,
)
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

if let Some(def_id) = def_id
&& self.tcx.def_kind(def_id) == hir::def::DefKind::Fn
&& matches!(self.tcx.intrinsic(def_id), Some(sym::const_eval_select))
&& self.tcx.is_intrinsic(def_id, sym::const_eval_select)
{
let fn_sig = self.resolve_vars_if_possible(fn_sig);
for idx in 0..=1 {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1227,7 +1227,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
}

fn def_id_is_transmute(cx: &LateContext<'_>, def_id: DefId) -> bool {
matches!(cx.tcx.intrinsic(def_id), Some(sym::transmute))
cx.tcx.is_intrinsic(def_id, sym::transmute)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1744,7 +1744,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
self.root.tables.attr_flags.get(self, index)
}

fn get_intrinsic(self, index: DefIndex) -> Option<Symbol> {
fn get_intrinsic(self, index: DefIndex) -> Option<ty::IntrinsicDef> {
self.root.tables.intrinsic.get(self, index).map(|d| d.decode(self))
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/rmeta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ macro_rules! define_tables {

define_tables! {
- defaulted:
intrinsic: Table<DefIndex, Option<LazyValue<Symbol>>>,
intrinsic: Table<DefIndex, Option<LazyValue<ty::IntrinsicDef>>>,
is_macro_rules: Table<DefIndex, bool>,
is_type_alias_impl_trait: Table<DefIndex, bool>,
type_alias_is_lazy: Table<DefIndex, bool>,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/query/erase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ trivial! {
Option<rustc_span::Span>,
Option<rustc_target::spec::PanicStrategy>,
Option<usize>,
Option<rustc_span::Symbol>,
Option<rustc_middle::ty::IntrinsicDef>,
Result<(), rustc_errors::ErrorGuaranteed>,
Result<(), rustc_middle::traits::query::NoSolution>,
Result<rustc_middle::traits::EvaluationResult, rustc_middle::traits::OverflowError>,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1748,7 +1748,7 @@ rustc_queries! {
separate_provide_extern
}
/// Whether the function is an intrinsic
query intrinsic(def_id: DefId) -> Option<Symbol> {
query intrinsic(def_id: DefId) -> Option<rustc_middle::ty::IntrinsicDef> {
desc { |tcx| "fetch intrinsic name if `{}` is an intrinsic", tcx.def_path_str(def_id) }
separate_provide_extern
}
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_middle/src/ty/intrinsic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use rustc_span::{def_id::DefId, Symbol};

use super::TyCtxt;

#[derive(Copy, Clone, Debug, Decodable, Encodable, HashStable)]
pub struct IntrinsicDef {
pub name: Symbol,
/// Whether the intrinsic has no meaningful body and all backends need to shim all calls to it.
pub must_be_overridden: bool,
}

impl TyCtxt<'_> {
pub fn is_intrinsic(self, def_id: DefId, name: Symbol) -> bool {
let Some(i) = self.intrinsic(def_id) else { return false };
i.name == name
}
}
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub use adt::*;
pub use assoc::*;
pub use generic_args::*;
pub use generics::*;
pub use intrinsic::IntrinsicDef;
use rustc_ast as ast;
use rustc_ast::node_id::NodeMap;
use rustc_attr as attr;
Expand Down Expand Up @@ -147,6 +148,7 @@ mod generic_args;
mod generics;
mod impls_ty;
mod instance;
mod intrinsic;
mod list;
mod opaque_types;
mod parameterized;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/parameterized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ trivially_parameterized_over_tcx! {
ty::Visibility<DefIndex>,
ty::adjustment::CoerceUnsizedInfo,
ty::fast_reject::SimplifiedType,
ty::IntrinsicDef,
rustc_ast::Attribute,
rustc_ast::DelimArgs,
rustc_ast::expand::StrippedCfgItem<rustc_hir::def_id::DefIndex>,
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
use rustc_index::bit_set::GrowableBitSet;
use rustc_macros::HashStable;
use rustc_session::Limit;
use rustc_span::{sym, Symbol};
use rustc_span::sym;
use rustc_target::abi::{Integer, IntegerType, Primitive, Size};
use rustc_target::spec::abi::Abi;
use smallvec::SmallVec;
Expand Down Expand Up @@ -1539,11 +1539,14 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
}

/// Determines whether an item is an intrinsic by Abi. or by whether it has a `rustc_intrinsic` attribute
pub fn intrinsic(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<Symbol> {
pub fn intrinsic(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::IntrinsicDef> {
if matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic | Abi::PlatformIntrinsic)
|| tcx.has_attr(def_id, sym::rustc_intrinsic)
{
Some(tcx.item_name(def_id.into()))
Some(ty::IntrinsicDef {
name: tcx.item_name(def_id.into()),
must_be_overridden: tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden),
})
} else {
None
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_dataflow/src/rustc_peek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ impl PeekCall {
&terminator.kind
{
if let ty::FnDef(def_id, fn_args) = *func.const_.ty().kind() {
if tcx.intrinsic(def_id)? != sym::rustc_peek {
if tcx.intrinsic(def_id)?.name != sym::rustc_peek {
return None;
}

Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_mir_transform/src/cross_crate_inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::InliningThreshold;
use rustc_session::config::OptLevel;
use rustc_span::sym;

pub fn provide(providers: &mut Providers) {
providers.cross_crate_inlinable = cross_crate_inlinable;
Expand All @@ -22,6 +23,10 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
return false;
}

if tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden) {
return false;
}

// This just reproduces the logic from Instance::requires_inline.
match tcx.def_kind(def_id) {
DefKind::Ctor(..) | DefKind::Closure => return true,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir_transform/src/instsimplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,8 @@ fn resolve_rust_intrinsic<'tcx>(
func_ty: Ty<'tcx>,
) -> Option<(Symbol, GenericArgsRef<'tcx>)> {
if let ty::FnDef(def_id, args) = *func_ty.kind() {
let name = tcx.intrinsic(def_id)?;
return Some((name, args));
let intrinsic = tcx.intrinsic(def_id)?;
return Some((intrinsic.name, args));
}
None
}
8 changes: 7 additions & 1 deletion compiler/rustc_mir_transform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ fn remap_mir_for_const_eval_select<'tcx>(
fn_span,
..
} if let ty::FnDef(def_id, _) = *const_.ty().kind()
&& matches!(tcx.intrinsic(def_id), Some(sym::const_eval_select)) =>
&& tcx.is_intrinsic(def_id, sym::const_eval_select) =>
{
let [tupled_args, called_in_const, called_at_rt]: [_; 3] =
std::mem::take(args).try_into().unwrap();
Expand Down Expand Up @@ -637,6 +637,12 @@ fn optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> &Body<'_> {
}

fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
if let Some(attr) = tcx.get_attr(did, sym::rustc_intrinsic_must_be_overridden) {
span_bug!(

Check failure on line 641 in compiler/rustc_mir_transform/src/lib.rs

View workflow job for this annotation

GitHub Actions / PR - x86_64-gnu-tools

this intrinsic must be overridden by the codegen backend, it has no meaningful body
attr.span,
"this intrinsic must be overridden by the codegen backend, it has no meaningful body",
)
}
if tcx.is_constructor(did.to_def_id()) {
// There's no reason to run all of the MIR passes on constructors when
// we can just output the MIR we want directly. This also saves const
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_mir_transform/src/lower_intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
if let TerminatorKind::Call { func, args, destination, target, .. } =
&mut terminator.kind
&& let ty::FnDef(def_id, generic_args) = *func.ty(local_decls, tcx).kind()
&& let Some(intrinsic_name) = tcx.intrinsic(def_id)
&& let Some(intrinsic) = tcx.intrinsic(def_id)
{
match intrinsic_name {
match intrinsic.name {
sym::unreachable => {
terminator.kind = TerminatorKind::Unreachable;
}
Expand Down Expand Up @@ -94,7 +94,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
lhs = args.next().unwrap();
rhs = args.next().unwrap();
}
let bin_op = match intrinsic_name {
let bin_op = match intrinsic.name {
sym::wrapping_add => BinOp::Add,
sym::wrapping_sub => BinOp::Sub,
sym::wrapping_mul => BinOp::Mul,
Expand Down Expand Up @@ -125,7 +125,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
lhs = args.next().unwrap();
rhs = args.next().unwrap();
}
let bin_op = match intrinsic_name {
let bin_op = match intrinsic.name {
sym::add_with_overflow => BinOp::Add,
sym::sub_with_overflow => BinOp::Sub,
sym::mul_with_overflow => BinOp::Mul,
Expand All @@ -144,7 +144,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
sym::size_of | sym::min_align_of => {
if let Some(target) = *target {
let tp_ty = generic_args.type_at(0);
let null_op = match intrinsic_name {
let null_op = match intrinsic.name {
sym::size_of => NullOp::SizeOf,
sym::min_align_of => NullOp::AlignOf,
_ => bug!("unexpected intrinsic"),
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,11 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
return false;
}

if tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden) {
// These are implemented by backends directly and have no meaningful body.
return false;
}

if def_id.is_local() {
// Local items cannot be referred to locally without monomorphizing them locally.
return true;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1412,6 +1412,7 @@ symbols! {
rustc_inherit_overflow_checks,
rustc_insignificant_dtor,
rustc_intrinsic,
rustc_intrinsic_must_be_overridden,
rustc_layout,
rustc_layout_scalar_valid_range_end,
rustc_layout_scalar_valid_range_start,
Expand Down
Loading

0 comments on commit 95d7abf

Please sign in to comment.