Rollup merge of #103977 - TimNN:memory-effects, r=nikic
LLVM 16: Switch to using MemoryEffects
This adapts the compiler to the changes required by 304f1d59ca
.
AFAICT, `WriteOnly` isn't used by the compiler, all `ReadNone` uses were migrated and the remaining use of `ReadOnly` is only for function parameters.
To simplify the FFI, this PR uses an enum to represent `MemoryEffects` across the FFI boundary, which then gets mapped to the matching static factory method when constructing the attribute.
Fixes #103961.
`@rustbot` label +llvm-main
r? `@nikic`
This commit is contained in:
commit
f6ca5aa19a
8 changed files with 67 additions and 12 deletions
|
@ -285,13 +285,13 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
||||||
let mut attrs = SmallVec::<[_; 2]>::new();
|
let mut attrs = SmallVec::<[_; 2]>::new();
|
||||||
if options.contains(InlineAsmOptions::PURE) {
|
if options.contains(InlineAsmOptions::PURE) {
|
||||||
if options.contains(InlineAsmOptions::NOMEM) {
|
if options.contains(InlineAsmOptions::NOMEM) {
|
||||||
attrs.push(llvm::AttributeKind::ReadNone.create_attr(self.cx.llcx));
|
attrs.push(llvm::MemoryEffects::None.create_attr(self.cx.llcx));
|
||||||
} else if options.contains(InlineAsmOptions::READONLY) {
|
} else if options.contains(InlineAsmOptions::READONLY) {
|
||||||
attrs.push(llvm::AttributeKind::ReadOnly.create_attr(self.cx.llcx));
|
attrs.push(llvm::MemoryEffects::ReadOnly.create_attr(self.cx.llcx));
|
||||||
}
|
}
|
||||||
attrs.push(llvm::AttributeKind::WillReturn.create_attr(self.cx.llcx));
|
attrs.push(llvm::AttributeKind::WillReturn.create_attr(self.cx.llcx));
|
||||||
} else if options.contains(InlineAsmOptions::NOMEM) {
|
} else if options.contains(InlineAsmOptions::NOMEM) {
|
||||||
attrs.push(llvm::AttributeKind::InaccessibleMemOnly.create_attr(self.cx.llcx));
|
attrs.push(llvm::MemoryEffects::InaccessibleMemOnly.create_attr(self.cx.llcx));
|
||||||
} else {
|
} else {
|
||||||
// LLVM doesn't have an attribute to represent ReadOnly + SideEffect
|
// LLVM doesn't have an attribute to represent ReadOnly + SideEffect
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::attributes;
|
use crate::attributes;
|
||||||
use crate::llvm::AttributePlace::Function;
|
use crate::llvm::AttributePlace::Function;
|
||||||
use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace};
|
use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace, MemoryEffects};
|
||||||
use crate::llvm_util;
|
use crate::llvm_util;
|
||||||
pub use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr};
|
pub use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr};
|
||||||
|
|
||||||
|
@ -303,10 +303,10 @@ pub fn from_fn_attrs<'ll, 'tcx>(
|
||||||
to_add.push(AttributeKind::ReturnsTwice.create_attr(cx.llcx));
|
to_add.push(AttributeKind::ReturnsTwice.create_attr(cx.llcx));
|
||||||
}
|
}
|
||||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) {
|
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) {
|
||||||
to_add.push(AttributeKind::ReadOnly.create_attr(cx.llcx));
|
to_add.push(MemoryEffects::ReadOnly.create_attr(cx.llcx));
|
||||||
}
|
}
|
||||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_CONST) {
|
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_CONST) {
|
||||||
to_add.push(AttributeKind::ReadNone.create_attr(cx.llcx));
|
to_add.push(MemoryEffects::None.create_attr(cx.llcx));
|
||||||
}
|
}
|
||||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||||
to_add.push(AttributeKind::Naked.create_attr(cx.llcx));
|
to_add.push(AttributeKind::Naked.create_attr(cx.llcx));
|
||||||
|
|
|
@ -183,7 +183,6 @@ pub enum AttributeKind {
|
||||||
OptimizeNone = 24,
|
OptimizeNone = 24,
|
||||||
ReturnsTwice = 25,
|
ReturnsTwice = 25,
|
||||||
ReadNone = 26,
|
ReadNone = 26,
|
||||||
InaccessibleMemOnly = 27,
|
|
||||||
SanitizeHWAddress = 28,
|
SanitizeHWAddress = 28,
|
||||||
WillReturn = 29,
|
WillReturn = 29,
|
||||||
StackProtectReq = 30,
|
StackProtectReq = 30,
|
||||||
|
@ -590,6 +589,15 @@ pub enum ChecksumKind {
|
||||||
SHA256,
|
SHA256,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// LLVMRustMemoryEffects
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub enum MemoryEffects {
|
||||||
|
None,
|
||||||
|
ReadOnly,
|
||||||
|
InaccessibleMemOnly,
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
type Opaque;
|
type Opaque;
|
||||||
}
|
}
|
||||||
|
@ -1175,6 +1183,7 @@ extern "C" {
|
||||||
pub fn LLVMRustCreateUWTableAttr(C: &Context, async_: bool) -> &Attribute;
|
pub fn LLVMRustCreateUWTableAttr(C: &Context, async_: bool) -> &Attribute;
|
||||||
pub fn LLVMRustCreateAllocSizeAttr(C: &Context, size_arg: u32) -> &Attribute;
|
pub fn LLVMRustCreateAllocSizeAttr(C: &Context, size_arg: u32) -> &Attribute;
|
||||||
pub fn LLVMRustCreateAllocKindAttr(C: &Context, size_arg: u64) -> &Attribute;
|
pub fn LLVMRustCreateAllocKindAttr(C: &Context, size_arg: u64) -> &Attribute;
|
||||||
|
pub fn LLVMRustCreateMemoryEffectsAttr(C: &Context, effects: MemoryEffects) -> &Attribute;
|
||||||
|
|
||||||
// Operations on functions
|
// Operations on functions
|
||||||
pub fn LLVMRustGetOrInsertFunction<'a>(
|
pub fn LLVMRustGetOrInsertFunction<'a>(
|
||||||
|
|
|
@ -185,6 +185,13 @@ impl AttributeKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MemoryEffects {
|
||||||
|
/// Create an LLVM Attribute with these memory effects.
|
||||||
|
pub fn create_attr(self, llcx: &Context) -> &Attribute {
|
||||||
|
unsafe { LLVMRustCreateMemoryEffectsAttr(llcx, self) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_section(llglobal: &Value, section_name: &str) {
|
pub fn set_section(llglobal: &Value, section_name: &str) {
|
||||||
let section_name_cstr = CString::new(section_name).expect("unexpected CString error");
|
let section_name_cstr = CString::new(section_name).expect("unexpected CString error");
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -76,7 +76,6 @@ enum LLVMRustAttribute {
|
||||||
OptimizeNone = 24,
|
OptimizeNone = 24,
|
||||||
ReturnsTwice = 25,
|
ReturnsTwice = 25,
|
||||||
ReadNone = 26,
|
ReadNone = 26,
|
||||||
InaccessibleMemOnly = 27,
|
|
||||||
SanitizeHWAddress = 28,
|
SanitizeHWAddress = 28,
|
||||||
WillReturn = 29,
|
WillReturn = 29,
|
||||||
StackProtectReq = 30,
|
StackProtectReq = 30,
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
#include "llvm/IR/Intrinsics.h"
|
#include "llvm/IR/Intrinsics.h"
|
||||||
#include "llvm/IR/IntrinsicsARM.h"
|
#include "llvm/IR/IntrinsicsARM.h"
|
||||||
#include "llvm/IR/Mangler.h"
|
#include "llvm/IR/Mangler.h"
|
||||||
|
#if LLVM_VERSION_GE(16, 0)
|
||||||
|
#include "llvm/IR/ModRef.h"
|
||||||
|
#endif
|
||||||
#include "llvm/Object/Archive.h"
|
#include "llvm/Object/Archive.h"
|
||||||
#include "llvm/Object/COFFImportFile.h"
|
#include "llvm/Object/COFFImportFile.h"
|
||||||
#include "llvm/Object/ObjectFile.h"
|
#include "llvm/Object/ObjectFile.h"
|
||||||
|
@ -213,8 +216,6 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
|
||||||
return Attribute::ReturnsTwice;
|
return Attribute::ReturnsTwice;
|
||||||
case ReadNone:
|
case ReadNone:
|
||||||
return Attribute::ReadNone;
|
return Attribute::ReadNone;
|
||||||
case InaccessibleMemOnly:
|
|
||||||
return Attribute::InaccessibleMemOnly;
|
|
||||||
case SanitizeHWAddress:
|
case SanitizeHWAddress:
|
||||||
return Attribute::SanitizeHWAddress;
|
return Attribute::SanitizeHWAddress;
|
||||||
case WillReturn:
|
case WillReturn:
|
||||||
|
@ -379,6 +380,43 @@ extern "C" LLVMAttributeRef LLVMRustCreateAllocKindAttr(LLVMContextRef C, uint64
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Simplified representation of `MemoryEffects` across the FFI boundary.
|
||||||
|
//
|
||||||
|
// Each variant corresponds to one of the static factory methods on `MemoryEffects`.
|
||||||
|
enum class LLVMRustMemoryEffects {
|
||||||
|
None,
|
||||||
|
ReadOnly,
|
||||||
|
InaccessibleMemOnly,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" LLVMAttributeRef LLVMRustCreateMemoryEffectsAttr(LLVMContextRef C,
|
||||||
|
LLVMRustMemoryEffects Effects) {
|
||||||
|
#if LLVM_VERSION_GE(16, 0)
|
||||||
|
switch (Effects) {
|
||||||
|
case LLVMRustMemoryEffects::None:
|
||||||
|
return wrap(Attribute::getWithMemoryEffects(*unwrap(C), MemoryEffects::none()));
|
||||||
|
case LLVMRustMemoryEffects::ReadOnly:
|
||||||
|
return wrap(Attribute::getWithMemoryEffects(*unwrap(C), MemoryEffects::readOnly()));
|
||||||
|
case LLVMRustMemoryEffects::InaccessibleMemOnly:
|
||||||
|
return wrap(Attribute::getWithMemoryEffects(*unwrap(C),
|
||||||
|
MemoryEffects::inaccessibleMemOnly()));
|
||||||
|
default:
|
||||||
|
report_fatal_error("bad MemoryEffects.");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
switch (Effects) {
|
||||||
|
case LLVMRustMemoryEffects::None:
|
||||||
|
return wrap(Attribute::get(*unwrap(C), Attribute::ReadNone));
|
||||||
|
case LLVMRustMemoryEffects::ReadOnly:
|
||||||
|
return wrap(Attribute::get(*unwrap(C), Attribute::ReadOnly));
|
||||||
|
case LLVMRustMemoryEffects::InaccessibleMemOnly:
|
||||||
|
return wrap(Attribute::get(*unwrap(C), Attribute::InaccessibleMemOnly));
|
||||||
|
default:
|
||||||
|
report_fatal_error("bad MemoryEffects.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Enable a fast-math flag
|
// Enable a fast-math flag
|
||||||
//
|
//
|
||||||
// https://llvm.org/docs/LangRef.html#fast-math-flags
|
// https://llvm.org/docs/LangRef.html#fast-math-flags
|
||||||
|
|
|
@ -7,6 +7,7 @@ pub fn bar() { unsafe { foo() } }
|
||||||
extern "C" {
|
extern "C" {
|
||||||
// CHECK-LABEL: declare{{.*}}void @foo()
|
// CHECK-LABEL: declare{{.*}}void @foo()
|
||||||
// CHECK-SAME: [[ATTRS:#[0-9]+]]
|
// CHECK-SAME: [[ATTRS:#[0-9]+]]
|
||||||
// CHECK-DAG: attributes [[ATTRS]] = { {{.*}}readnone{{.*}} }
|
// The attribute changed from `readnone` to `memory(none)` with LLVM 16.0.
|
||||||
|
// CHECK-DAG: attributes [[ATTRS]] = { {{.*}}{{readnone|memory\(none\)}}{{.*}} }
|
||||||
#[ffi_const] pub fn foo();
|
#[ffi_const] pub fn foo();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ pub fn bar() { unsafe { foo() } }
|
||||||
extern "C" {
|
extern "C" {
|
||||||
// CHECK-LABEL: declare{{.*}}void @foo()
|
// CHECK-LABEL: declare{{.*}}void @foo()
|
||||||
// CHECK-SAME: [[ATTRS:#[0-9]+]]
|
// CHECK-SAME: [[ATTRS:#[0-9]+]]
|
||||||
// CHECK-DAG: attributes [[ATTRS]] = { {{.*}}readonly{{.*}} }
|
// The attribute changed from `readonly` to `memory(read)` with LLVM 16.0.
|
||||||
|
// CHECK-DAG: attributes [[ATTRS]] = { {{.*}}{{readonly|memory\(read\)}}{{.*}} }
|
||||||
#[ffi_pure] pub fn foo();
|
#[ffi_pure] pub fn foo();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue