diff options
Diffstat (limited to 'compiler/rustc_codegen_llvm/src')
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/abi.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/attributes.rs | 52 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/builder.rs | 38 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/llvm/mod.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/llvm_util.rs | 10 |
6 files changed, 85 insertions, 52 deletions
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index f8f6956c47e..b14a4f28c75 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -561,8 +561,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { if self.conv == Conv::CCmseNonSecureCall { // This will probably get ignored on all targets but those supporting the TrustZone-M // extension (thumbv8m targets). - let cmse_nonsecure_call = - llvm::CreateAttrString(bx.cx.llcx, cstr::cstr!("cmse_nonsecure_call")); + let cmse_nonsecure_call = llvm::CreateAttrString(bx.cx.llcx, "cmse_nonsecure_call"); attributes::apply_to_callsite( callsite, llvm::AttributePlace::Function, diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index e382af8880b..6fd836946ff 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -1,10 +1,6 @@ //! Set and unset common attributes on LLVM values. -use std::ffi::CString; - -use cstr::cstr; use rustc_codegen_ssa::traits::*; -use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty::{self, TyCtxt}; @@ -103,11 +99,11 @@ pub fn frame_pointer_type_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attr fp = FramePointer::Always; } let attr_value = match fp { - FramePointer::Always => cstr!("all"), - FramePointer::NonLeaf => cstr!("non-leaf"), + FramePointer::Always => "all", + FramePointer::NonLeaf => "non-leaf", FramePointer::MayOmit => return None, }; - Some(llvm::CreateAttrStringValue(cx.llcx, cstr!("frame-pointer"), attr_value)) + Some(llvm::CreateAttrStringValue(cx.llcx, "frame-pointer", attr_value)) } /// Tell LLVM what instrument function to insert. @@ -119,11 +115,11 @@ fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribu // The function name varies on platforms. // See test/CodeGen/mcount.c in clang. - let mcount_name = CString::new(cx.sess().target.mcount.as_str().as_bytes()).unwrap(); + let mcount_name = cx.sess().target.mcount.as_str(); Some(llvm::CreateAttrStringValue( cx.llcx, - cstr!("instrument-function-entry-inlined"), + "instrument-function-entry-inlined", &mcount_name, )) } else { @@ -159,20 +155,20 @@ fn probestack_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { StackProbeType::None => return None, // Request LLVM to generate the probes inline. If the given LLVM version does not support // this, no probe is generated at all (even if the attribute is specified). - StackProbeType::Inline => cstr!("inline-asm"), + StackProbeType::Inline => "inline-asm", // Flag our internal `__rust_probestack` function as the stack probe symbol. // This is defined in the `compiler-builtins` crate for each architecture. - StackProbeType::Call => cstr!("__rust_probestack"), + StackProbeType::Call => "__rust_probestack", // Pick from the two above based on the LLVM version. StackProbeType::InlineOrCall { min_llvm_version_for_inline } => { if llvm_util::get_version() < min_llvm_version_for_inline { - cstr!("__rust_probestack") + "__rust_probestack" } else { - cstr!("inline-asm") + "inline-asm" } } }; - Some(llvm::CreateAttrStringValue(cx.llcx, cstr!("probe-stack"), attr_value)) + Some(llvm::CreateAttrStringValue(cx.llcx, "probe-stack", attr_value)) } fn stackprotector_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { @@ -187,15 +183,13 @@ fn stackprotector_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { } pub fn target_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll Attribute { - let target_cpu = SmallCStr::new(llvm_util::target_cpu(cx.tcx.sess)); - llvm::CreateAttrStringValue(cx.llcx, cstr!("target-cpu"), target_cpu.as_c_str()) + let target_cpu = llvm_util::target_cpu(cx.tcx.sess); + llvm::CreateAttrStringValue(cx.llcx, "target-cpu", target_cpu) } pub fn tune_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { - llvm_util::tune_cpu(cx.tcx.sess).map(|tune| { - let tune_cpu = SmallCStr::new(tune); - llvm::CreateAttrStringValue(cx.llcx, cstr!("tune-cpu"), tune_cpu.as_c_str()) - }) + llvm_util::tune_cpu(cx.tcx.sess) + .map(|tune_cpu| llvm::CreateAttrStringValue(cx.llcx, "tune-cpu", tune_cpu)) } /// Get the `NonLazyBind` LLVM attribute, @@ -280,7 +274,7 @@ pub fn from_fn_attrs<'ll, 'tcx>( } if cx.sess().opts.debugging_opts.profile_sample_use.is_some() { - to_add.push(llvm::CreateAttrString(cx.llcx, cstr!("use-sample-profile"))); + to_add.push(llvm::CreateAttrString(cx.llcx, "use-sample-profile")); } // FIXME: none of these three functions interact with source level attributes. @@ -310,7 +304,7 @@ pub fn from_fn_attrs<'ll, 'tcx>( attributes::apply_to_llfn(llfn, AttributePlace::ReturnValue, &[no_alias]); } if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY) { - to_add.push(llvm::CreateAttrString(cx.llcx, cstr!("cmse_nonsecure_entry"))); + to_add.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry")); } if let Some(align) = codegen_fn_attrs.alignment { llvm::set_alignment(llfn, align as usize); @@ -363,12 +357,12 @@ pub fn from_fn_attrs<'ll, 'tcx>( // If this function is an import from the environment but the wasm // import has a specific module/name, apply them here. if let Some(module) = wasm_import_module(cx.tcx, instance.def_id()) { - to_add.push(llvm::CreateAttrStringValue(cx.llcx, cstr!("wasm-import-module"), &module)); + to_add.push(llvm::CreateAttrStringValue(cx.llcx, "wasm-import-module", &module)); let name = codegen_fn_attrs.link_name.unwrap_or_else(|| cx.tcx.item_name(instance.def_id())); - let name = CString::new(name.as_str()).unwrap(); - to_add.push(llvm::CreateAttrStringValue(cx.llcx, cstr!("wasm-import-name"), &name)); + let name = name.as_str(); + to_add.push(llvm::CreateAttrStringValue(cx.llcx, "wasm-import-name", name)); } // The `"wasm"` abi on wasm targets automatically enables the @@ -388,13 +382,13 @@ pub fn from_fn_attrs<'ll, 'tcx>( let val = global_features .chain(function_features.iter().map(|s| &s[..])) .intersperse(",") - .collect::<SmallCStr>(); - to_add.push(llvm::CreateAttrStringValue(cx.llcx, cstr!("target-features"), &val)); + .collect::<String>(); + to_add.push(llvm::CreateAttrStringValue(cx.llcx, "target-features", &val)); } attributes::apply_to_llfn(llfn, Function, &to_add); } -fn wasm_import_module(tcx: TyCtxt<'_>, id: DefId) -> Option<CString> { - tcx.wasm_import_module_map(id.krate).get(&id).map(|s| CString::new(&s[..]).unwrap()) +fn wasm_import_module(tcx: TyCtxt<'_>, id: DefId) -> Option<&String> { + tcx.wasm_import_module_map(id.krate).get(&id) } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 6c1d4ce8f3c..c4eb593d297 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -477,6 +477,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { bx: &mut Builder<'a, 'll, 'tcx>, load: &'ll Value, scalar: abi::Scalar, + layout: TyAndLayout<'tcx>, + offset: Size, ) { if !scalar.is_always_valid(bx) { bx.noundef_metadata(load); @@ -488,10 +490,18 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { bx.range_metadata(load, scalar.valid_range); } } - abi::Pointer if !scalar.valid_range.contains(0) => { - bx.nonnull_metadata(load); + abi::Pointer => { + if !scalar.valid_range.contains(0) { + bx.nonnull_metadata(load); + } + + if let Some(pointee) = layout.pointee_info_at(bx, offset) { + if let Some(_) = pointee.safe { + bx.align_metadata(load, pointee.align); + } + } } - _ => {} + abi::F32 | abi::F64 => {} } } @@ -509,7 +519,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let llval = const_llval.unwrap_or_else(|| { let load = self.load(place.layout.llvm_type(self), place.llval, place.align); if let abi::Abi::Scalar(scalar) = place.layout.abi { - scalar_load_metadata(self, load, scalar); + scalar_load_metadata(self, load, scalar, place.layout, Size::ZERO); } load }); @@ -518,17 +528,17 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let b_offset = a.value.size(self).align_to(b.value.align(self).abi); let pair_ty = place.layout.llvm_type(self); - let mut load = |i, scalar: abi::Scalar, align| { + let mut load = |i, scalar: abi::Scalar, layout, align, offset| { let llptr = self.struct_gep(pair_ty, place.llval, i as u64); let llty = place.layout.scalar_pair_element_llvm_type(self, i, false); let load = self.load(llty, llptr, align); - scalar_load_metadata(self, load, scalar); + scalar_load_metadata(self, load, scalar, layout, offset); self.to_immediate_scalar(load, scalar) }; OperandValue::Pair( - load(0, a, place.align), - load(1, b, place.align.restrict_for_offset(b_offset)), + load(0, a, place.layout, place.align, Size::ZERO), + load(1, b, place.layout, place.align.restrict_for_offset(b_offset), b_offset), ) } else { OperandValue::Ref(place.llval, None, place.align) @@ -1208,6 +1218,18 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { } } + fn align_metadata(&mut self, load: &'ll Value, align: Align) { + unsafe { + let v = [self.cx.const_u64(align.bytes())]; + + llvm::LLVMSetMetadata( + load, + llvm::MD_align as c_uint, + llvm::LLVMMDNodeInContext(self.cx.llcx, v.as_ptr(), v.len() as c_uint), + ); + } + } + fn noundef_metadata(&mut self, load: &'ll Value) { unsafe { llvm::LLVMSetMetadata( diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 4a8894983b9..375b9927c86 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -441,6 +441,7 @@ pub enum MetadataType { MD_nontemporal = 9, MD_mem_parallel_loop_access = 10, MD_nonnull = 11, + MD_align = 17, MD_type = 19, MD_noundef = 29, } @@ -576,12 +577,12 @@ pub enum PassKind { Module, } -/// LLVMRustThinLTOData +// LLVMRustThinLTOData extern "C" { pub type ThinLTOData; } -/// LLVMRustThinLTOBuffer +// LLVMRustThinLTOBuffer extern "C" { pub type ThinLTOBuffer; } @@ -1175,11 +1176,12 @@ extern "C" { // Operations on attributes pub fn LLVMRustCreateAttrNoValue(C: &Context, attr: AttributeKind) -> &Attribute; - pub fn LLVMRustCreateAttrString(C: &Context, Name: *const c_char) -> &Attribute; - pub fn LLVMRustCreateAttrStringValue( + pub fn LLVMCreateStringAttribute( C: &Context, Name: *const c_char, + NameLen: c_uint, Value: *const c_char, + ValueLen: c_uint, ) -> &Attribute; pub fn LLVMRustCreateAlignmentAttr(C: &Context, bytes: u64) -> &Attribute; pub fn LLVMRustCreateDereferenceableAttr(C: &Context, bytes: u64) -> &Attribute; diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 4892b8d4a84..48fbc1de8ee 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -47,12 +47,28 @@ pub fn AddCallSiteAttributes<'ll>( } } -pub fn CreateAttrStringValue<'ll>(llcx: &'ll Context, attr: &CStr, value: &CStr) -> &'ll Attribute { - unsafe { LLVMRustCreateAttrStringValue(llcx, attr.as_ptr(), value.as_ptr()) } +pub fn CreateAttrStringValue<'ll>(llcx: &'ll Context, attr: &str, value: &str) -> &'ll Attribute { + unsafe { + LLVMCreateStringAttribute( + llcx, + attr.as_ptr().cast(), + attr.len().try_into().unwrap(), + value.as_ptr().cast(), + value.len().try_into().unwrap(), + ) + } } -pub fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &CStr) -> &'ll Attribute { - unsafe { LLVMRustCreateAttrStringValue(llcx, attr.as_ptr(), std::ptr::null()) } +pub fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &str) -> &'ll Attribute { + unsafe { + LLVMCreateStringAttribute( + llcx, + attr.as_ptr().cast(), + attr.len().try_into().unwrap(), + std::ptr::null(), + 0, + ) + } } pub fn CreateAlignmentAttr(llcx: &Context, bytes: u64) -> &Attribute { diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 3b06587061d..e9d13a4ebaf 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -369,12 +369,12 @@ pub fn target_cpu(sess: &Session) -> &str { /// The list of LLVM features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`, /// `--target` and similar). pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<String> { - // Features that come earlier are overriden by conflicting features later in the string. + // Features that come earlier are overridden by conflicting features later in the string. // Typically we'll want more explicit settings to override the implicit ones, so: // - // * Features from -Ctarget-cpu=*; are overriden by [^1] - // * Features implied by --target; are overriden by - // * Features from -Ctarget-feature; are overriden by + // * Features from -Ctarget-cpu=*; are overridden by [^1] + // * Features implied by --target; are overridden by + // * Features from -Ctarget-feature; are overridden by // * function specific features. // // [^1]: target-cpu=native is handled here, other target-cpu values are handled implicitly @@ -383,7 +383,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str // FIXME(nagisa): it isn't clear what's the best interaction between features implied by // `-Ctarget-cpu` and `--target` are. On one hand, you'd expect CLI arguments to always // override anything that's implicit, so e.g. when there's no `--target` flag, features implied - // the host target are overriden by `-Ctarget-cpu=*`. On the other hand, what about when both + // the host target are overridden by `-Ctarget-cpu=*`. On the other hand, what about when both // `--target` and `-Ctarget-cpu=*` are specified? Both then imply some target features and both // flags are specified by the user on the CLI. It isn't as clear-cut which order of precedence // should be taken in cases like these. |
