}
pub trait ArgAttributesExt {
- fn apply_attrs_to_llfn(&self, idx: AttributePlace, llfn: &Value);
- fn apply_attrs_to_callsite(&self, idx: AttributePlace, callsite: &Value);
+ fn apply_attrs_to_llfn(&self, idx: AttributePlace, cx: &CodegenCx<'_, '_>, llfn: &Value);
+ fn apply_attrs_to_callsite(
+ &self,
+ idx: AttributePlace,
+ cx: &CodegenCx<'_, '_>,
+ callsite: &Value,
+ );
+}
+
+fn should_use_mutable_noalias(cx: &CodegenCx<'_, '_>) -> bool {
+ // While #84958 has been fixed, mutable noalias is not enabled by default
+ // in Rust 1.53 out of an abundance of caution.
+ cx.tcx.sess.opts.debugging_opts.mutable_noalias.unwrap_or(false)
}
impl ArgAttributesExt for ArgAttributes {
- fn apply_attrs_to_llfn(&self, idx: AttributePlace, llfn: &Value) {
+ fn apply_attrs_to_llfn(&self, idx: AttributePlace, cx: &CodegenCx<'_, '_>, llfn: &Value) {
let mut regular = self.regular;
unsafe {
let deref = self.pointee_size.bytes();
llvm::LLVMRustAddAlignmentAttr(llfn, idx.as_uint(), align.bytes() as u32);
}
regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn));
+ if regular.contains(ArgAttribute::NoAliasMutRef) && should_use_mutable_noalias(cx) {
+ llvm::Attribute::NoAlias.apply_llfn(idx, llfn);
+ }
match self.arg_ext {
ArgExtension::None => {}
ArgExtension::Zext => {
}
}
- fn apply_attrs_to_callsite(&self, idx: AttributePlace, callsite: &Value) {
+ fn apply_attrs_to_callsite(
+ &self,
+ idx: AttributePlace,
+ cx: &CodegenCx<'_, '_>,
+ callsite: &Value,
+ ) {
let mut regular = self.regular;
unsafe {
let deref = self.pointee_size.bytes();
);
}
regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite));
+ if regular.contains(ArgAttribute::NoAliasMutRef) && should_use_mutable_noalias(cx) {
+ llvm::Attribute::NoAlias.apply_callsite(idx, callsite);
+ }
match self.arg_ext {
ArgExtension::None => {}
ArgExtension::Zext => {
let mut i = 0;
let mut apply = |attrs: &ArgAttributes| {
- attrs.apply_attrs_to_llfn(llvm::AttributePlace::Argument(i), llfn);
+ attrs.apply_attrs_to_llfn(llvm::AttributePlace::Argument(i), cx, llfn);
i += 1;
i - 1
};
match self.ret.mode {
PassMode::Direct(ref attrs) => {
- attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, llfn);
+ attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn);
}
PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => {
assert!(!on_stack);
// FIXME(wesleywiser, eddyb): We should apply `nounwind` and `noreturn` as appropriate to this callsite.
let mut i = 0;
- let mut apply = |attrs: &ArgAttributes| {
- attrs.apply_attrs_to_callsite(llvm::AttributePlace::Argument(i), callsite);
+ let mut apply = |cx: &CodegenCx<'_, '_>, attrs: &ArgAttributes| {
+ attrs.apply_attrs_to_callsite(llvm::AttributePlace::Argument(i), cx, callsite);
i += 1;
i - 1
};
match self.ret.mode {
PassMode::Direct(ref attrs) => {
- attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, callsite);
+ attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, &bx.cx, callsite);
}
PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => {
assert!(!on_stack);
- let i = apply(attrs);
+ let i = apply(bx.cx, attrs);
unsafe {
llvm::LLVMRustAddStructRetCallSiteAttr(
callsite,
}
for arg in &self.args {
if arg.pad.is_some() {
- apply(&ArgAttributes::new());
+ apply(bx.cx, &ArgAttributes::new());
}
match arg.mode {
PassMode::Ignore => {}
PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: true } => {
- let i = apply(attrs);
+ let i = apply(bx.cx, attrs);
unsafe {
llvm::LLVMRustAddByValCallSiteAttr(
callsite,
}
PassMode::Direct(ref attrs)
| PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: false } => {
- apply(attrs);
+ apply(bx.cx, attrs);
}
PassMode::Indirect {
ref attrs,
extra_attrs: Some(ref extra_attrs),
on_stack: _,
} => {
- apply(attrs);
- apply(extra_attrs);
+ apply(bx.cx, attrs);
+ apply(bx.cx, extra_attrs);
}
PassMode::Pair(ref a, ref b) => {
- apply(a);
- apply(b);
+ apply(bx.cx, a);
+ apply(bx.cx, b);
}
PassMode::Cast(_) => {
- apply(&ArgAttributes::new());
+ apply(bx.cx, &ArgAttributes::new());
}
}
}