From 3ca6ad922eb6d8c3139d961c844a0194eaf58770 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 27 Mar 2018 16:44:03 +0200 Subject: Use ScalarPair for tagged enums --- src/test/codegen/align-struct.rs | 3 +-- src/test/codegen/function-arguments.rs | 12 ++++++++++++ src/test/codegen/lifetime_start_end.rs | 8 ++++---- 3 files changed, 17 insertions(+), 6 deletions(-) (limited to 'src/test/codegen') diff --git a/src/test/codegen/align-struct.rs b/src/test/codegen/align-struct.rs index 155319cb154..f306608f432 100644 --- a/src/test/codegen/align-struct.rs +++ b/src/test/codegen/align-struct.rs @@ -29,7 +29,6 @@ pub enum Enum4 { A(i32), B(i32), } -// CHECK: %Enum4 = type { [0 x i32], i32, [1 x i32] } // CHECK: %"Enum4::A" = type { [1 x i32], i32, [0 x i32] } pub enum Enum64 { @@ -59,7 +58,7 @@ pub fn nested64(a: Align64, b: i32, c: i32, d: i8) -> Nested64 { // CHECK-LABEL: @enum4 #[no_mangle] pub fn enum4(a: i32) -> Enum4 { -// CHECK: %e4 = alloca %Enum4, align 4 +// CHECK: %e4 = alloca { i32, i32 }, align 4 let e4 = Enum4::A(a); e4 } diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index de302c69056..40a9ea5a181 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -145,6 +145,18 @@ pub fn return_slice(x: &[u16]) -> &[u16] { x } +// CHECK: { i16, i16 } @enum_id_1(i16 %x.0, i16 %x.1) +#[no_mangle] +pub fn enum_id_1(x: Option>) -> Option> { + x +} + +// CHECK: i16 @enum_id_2(i16) +#[no_mangle] +pub fn enum_id_2(x: Option) -> Option { + x +} + // CHECK: noalias i8* @allocator() #[no_mangle] #[allocator] diff --git a/src/test/codegen/lifetime_start_end.rs b/src/test/codegen/lifetime_start_end.rs index 62aa93398ac..ea3f0de5d08 100644 --- a/src/test/codegen/lifetime_start_end.rs +++ b/src/test/codegen/lifetime_start_end.rs @@ -25,16 +25,16 @@ pub fn test() { let b = &Some(a); &b; // keep variable in an alloca -// CHECK: [[S_b:%[0-9]+]] = bitcast %"core::option::Option"** %b to i8* +// CHECK: [[S_b:%[0-9]+]] = bitcast { i32, i32 }** %b to i8* // CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, i8* [[S_b]]) -// CHECK: [[S__4:%[0-9]+]] = bitcast %"core::option::Option"* %_4 to i8* +// CHECK: [[S__4:%[0-9]+]] = bitcast { i32, i32 }* %_4 to i8* // CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, i8* [[S__4]]) -// CHECK: [[E_b:%[0-9]+]] = bitcast %"core::option::Option"** %b to i8* +// CHECK: [[E_b:%[0-9]+]] = bitcast { i32, i32 }** %b to i8* // CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, i8* [[E_b]]) -// CHECK: [[E__4:%[0-9]+]] = bitcast %"core::option::Option"* %_4 to i8* +// CHECK: [[E__4:%[0-9]+]] = bitcast { i32, i32 }* %_4 to i8* // CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, i8* [[E__4]]) } -- cgit 1.4.1-3-g733a5 From 90656441a9dfbc42b6f5f1f25abeead66012bb00 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 22 Apr 2018 18:40:54 +0200 Subject: Emit range metadata on calls returning scalars (fixes #50157) --- src/librustc_target/abi/mod.rs | 19 ++++++++++++++++++- src/librustc_target/lib.rs | 1 + src/librustc_trans/abi.rs | 22 ++++++++++++++++++++-- src/librustc_trans/lib.rs | 1 + src/librustc_trans/mir/block.rs | 4 ++-- src/librustc_trans/mir/place.rs | 23 +++++++---------------- src/test/codegen/call-metadata.rs | 29 +++++++++++++++++++++++++++++ 7 files changed, 78 insertions(+), 21 deletions(-) create mode 100644 src/test/codegen/call-metadata.rs (limited to 'src/test/codegen') diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 18dd04c0ee8..346e5667a7b 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -14,7 +14,7 @@ pub use self::Primitive::*; use spec::Target; use std::cmp; -use std::ops::{Add, Deref, Sub, Mul, AddAssign, RangeInclusive}; +use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive}; pub mod call; @@ -544,6 +544,23 @@ impl Scalar { false } } + + /// Returns the valid range as a `x..y` range. + /// + /// If `x` and `y` are equal, the range is full, not empty. + pub fn valid_range_exclusive(&self, cx: C) -> Range { + // For a (max) value of -1, max will be `-1 as usize`, which overflows. + // However, that is fine here (it would still represent the full range), + // i.e., if the range is everything. + let bits = self.value.size(cx).bits(); + assert!(bits <= 128); + let mask = !0u128 >> (128 - bits); + let start = self.valid_range.start; + let end = self.valid_range.end; + assert_eq!(start, start & mask); + assert_eq!(end, end & mask); + start..(end.wrapping_add(1) & mask) + } } /// Describes how the fields of a type are located in memory. diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index 8f491157439..927d5c7e15a 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -29,6 +29,7 @@ #![feature(const_fn)] #![feature(fs_read_write)] #![feature(inclusive_range)] +#![feature(inclusive_range_fields)] #![feature(slice_patterns)] #[macro_use] diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 483f36afe27..1d0d7ec601f 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -265,7 +265,7 @@ pub trait FnTypeExt<'a, 'tcx> { fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type; fn llvm_cconv(&self) -> llvm::CallConv; fn apply_attrs_llfn(&self, llfn: ValueRef); - fn apply_attrs_callsite(&self, callsite: ValueRef); + fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef); } impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { @@ -640,7 +640,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { } } - fn apply_attrs_callsite(&self, callsite: ValueRef) { + fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef) { let mut i = 0; let mut apply = |attrs: &ArgAttributes| { attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite); @@ -653,6 +653,24 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { PassMode::Indirect(ref attrs) => apply(attrs), _ => {} } + if let layout::Abi::Scalar(ref scalar) = self.ret.layout.abi { + // If the value is a boolean, the range is 0..2 and that ultimately + // become 0..0 when the type becomes i1, which would be rejected + // by the LLVM verifier. + match scalar.value { + layout::Int(..) if !scalar.is_bool() => { + let range = scalar.valid_range_exclusive(bx.cx); + if range.start != range.end { + // FIXME(nox): This causes very weird type errors about + // SHL operators in constants in stage 2 with LLVM 3.9. + if unsafe { llvm::LLVMRustVersionMajor() >= 4 } { + bx.range_metadata(callsite, range); + } + } + } + _ => {} + } + } for arg in &self.args { if arg.pad.is_some() { apply(&ArgAttributes::new()); diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index dab01abd335..96a10e8b99d 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -25,6 +25,7 @@ #![allow(unused_attributes)] #![feature(libc)] #![feature(quote)] +#![feature(range_contains)] #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] #![feature(optin_builtin_traits)] diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 36f03605fea..b9e272e993e 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -127,7 +127,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { ret_bx, llblock(this, cleanup), cleanup_bundle); - fn_ty.apply_attrs_callsite(invokeret); + fn_ty.apply_attrs_callsite(&bx, invokeret); if let Some((ret_dest, target)) = destination { let ret_bx = this.build_block(target); @@ -136,7 +136,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } else { let llret = bx.call(fn_ptr, &llargs, cleanup_bundle); - fn_ty.apply_attrs_callsite(llret); + fn_ty.apply_attrs_callsite(&bx, llret); if this.mir[bb].is_cleanup { // Cleanup is always the cold path. Don't inline // drop glue. Also, when there is a deeply-nested diff --git a/src/librustc_trans/mir/place.rs b/src/librustc_trans/mir/place.rs index b340d91b027..680c7038998 100644 --- a/src/librustc_trans/mir/place.rs +++ b/src/librustc_trans/mir/place.rs @@ -91,24 +91,15 @@ impl<'a, 'tcx> PlaceRef<'tcx> { } let scalar_load_metadata = |load, scalar: &layout::Scalar| { - let (min, max) = (scalar.valid_range.start, scalar.valid_range.end); - let max_next = max.wrapping_add(1); - let bits = scalar.value.size(bx.cx).bits(); - assert!(bits <= 128); - let mask = !0u128 >> (128 - bits); - // For a (max) value of -1, max will be `-1 as usize`, which overflows. - // However, that is fine here (it would still represent the full range), - // i.e., if the range is everything. The lo==hi case would be - // rejected by the LLVM verifier (it would mean either an - // empty set, which is impossible, or the entire range of the - // type, which is pointless). + let vr = scalar.valid_range.clone(); match scalar.value { - layout::Int(..) if max_next & mask != min & mask => { - // llvm::ConstantRange can deal with ranges that wrap around, - // so an overflow on (max + 1) is fine. - bx.range_metadata(load, min..max_next); + layout::Int(..) => { + let range = scalar.valid_range_exclusive(bx.cx); + if range.start != range.end { + bx.range_metadata(load, range); + } } - layout::Pointer if 0 < min && min < max => { + layout::Pointer if vr.start < vr.end && !vr.contains(&0) => { bx.nonnull_metadata(load); } _ => {} diff --git a/src/test/codegen/call-metadata.rs b/src/test/codegen/call-metadata.rs new file mode 100644 index 00000000000..20d42ed852d --- /dev/null +++ b/src/test/codegen/call-metadata.rs @@ -0,0 +1,29 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Checks that range metadata gets emitted on calls to functions returning a +// scalar value. + +// compile-flags: -C no-prepopulate-passes +// min-llvm-version 4.0 + + +#![crate_type = "lib"] + +pub fn test() { + // CHECK: call i8 @some_true(), !range [[R0:![0-9]+]] + // CHECK: [[R0]] = !{i8 0, i8 3} + some_true(); +} + +#[no_mangle] +fn some_true() -> Option { + Some(true) +} -- cgit 1.4.1-3-g733a5 From 69ec4aa97c23cfc316ec340d1afcaaeb4877e8ef Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 28 Apr 2018 20:35:26 +0200 Subject: Mark functions returning uninhabited types as noreturn --- src/librustc_trans/debuginfo/mod.rs | 2 +- src/librustc_trans/declare.rs | 4 ++-- src/test/codegen/noreturnflag.rs | 22 ++++++++++++++++------ 3 files changed, 19 insertions(+), 9 deletions(-) (limited to 'src/test/codegen') diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 193db15303f..30676b91620 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -271,7 +271,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } None => {} }; - if sig.output().is_never() { + if cx.layout_of(sig.output()).abi == ty::layout::Abi::Uninhabited { flags = flags | DIFlags::FlagNoReturn; } diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs index bbe4e18b18c..97721ffbf06 100644 --- a/src/librustc_trans/declare.rs +++ b/src/librustc_trans/declare.rs @@ -23,6 +23,7 @@ use llvm::{self, ValueRef}; use llvm::AttributePlace::Function; use rustc::ty::{self, Ty}; +use rustc::ty::layout::{self, LayoutOf}; use rustc::session::config::Sanitizer; use rustc_target::spec::PanicStrategy; use abi::{Abi, FnType, FnTypeExt}; @@ -133,8 +134,7 @@ pub fn declare_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name: &str, let fty = FnType::new(cx, sig, &[]); let llfn = declare_raw_fn(cx, name, fty.llvm_cconv(), fty.llvm_type(cx)); - // FIXME(canndrew): This is_never should really be an is_uninhabited - if sig.output().is_never() { + if cx.layout_of(sig.output()).abi == layout::Abi::Uninhabited { llvm::Attribute::NoReturn.apply_llfn(Function, llfn); } diff --git a/src/test/codegen/noreturnflag.rs b/src/test/codegen/noreturnflag.rs index 24a5a4e44cb..7239223ca20 100644 --- a/src/test/codegen/noreturnflag.rs +++ b/src/test/codegen/noreturnflag.rs @@ -8,17 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -g -C no-prepopulate-passes // ignore-tidy-linelength // min-llvm-version 4.0 -// compile-flags: -g -C no-prepopulate-passes - -// CHECK: {{.*}}DISubprogram{{.*}}name: "foo"{{.*}}DIFlagNoReturn +#![crate_type = "lib"] -fn foo() -> ! { +#[no_mangle] +pub fn foo() -> ! { +// CHECK: @foo() unnamed_addr #0 loop {} } -pub fn main() { - foo(); +pub enum EmptyEnum {} + +#[no_mangle] +pub fn bar() -> EmptyEnum { +// CHECK: @bar() unnamed_addr #0 + loop {} } + +// CHECK: attributes #0 = {{{.*}} noreturn {{.*}}} + +// CHECK: DISubprogram(name: "foo", {{.*}} DIFlagNoReturn +// CHECK: DISubprogram(name: "bar", {{.*}} DIFlagNoReturn -- cgit 1.4.1-3-g733a5 From 622371153c66f9e371f587205d14040534060c18 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 23 Apr 2018 15:17:07 -0700 Subject: Add `-C target-feature` to all functions Previously the features specified to LLVM via `-C target-feature` were only reflected in the `TargetMachine` but this change *also* reflects these and the base features inside each function itself. This change matches clang and... Closes rust-lang-nursery/stdsimd#427 --- src/librustc_trans/attributes.rs | 30 ++++++++++++++++++------ src/librustc_trans/back/write.rs | 31 ++++--------------------- src/test/codegen/target-feature-on-functions.rs | 19 +++++++++++++++ 3 files changed, 47 insertions(+), 33 deletions(-) create mode 100644 src/test/codegen/target-feature-on-functions.rs (limited to 'src/test/codegen') diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs index eb5c7396ae0..f455c19cc0b 100644 --- a/src/librustc_trans/attributes.rs +++ b/src/librustc_trans/attributes.rs @@ -14,6 +14,7 @@ use std::ffi::{CStr, CString}; use rustc::hir::{self, TransFnAttrFlags}; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::session::Session; use rustc::session::config::Sanitizer; use rustc::ty::TyCtxt; use rustc::ty::maps::Providers; @@ -104,6 +105,18 @@ pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) { cstr("probe-stack\0"), cstr("__rust_probestack\0")); } +pub fn llvm_target_features(sess: &Session) -> impl Iterator { + const RUSTC_SPECIFIC_FEATURES: &[&str] = &[ + "crt-static", + ]; + + let cmdline = sess.opts.cg.target_feature.split(',') + .filter(|f| !RUSTC_SPECIFIC_FEATURES.iter().any(|s| f.contains(s))); + sess.target.target.options.features.split(',') + .chain(cmdline) + .filter(|l| !l.is_empty()) +} + /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute]) /// attributes. pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) { @@ -131,13 +144,16 @@ pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) { unwind(llfn, false); } - let features = - trans_fn_attrs.target_features - .iter() - .map(|f| { - let feature = &*f.as_str(); - format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature)) - }) + let features = llvm_target_features(cx.tcx.sess) + .map(|s| s.to_string()) + .chain( + trans_fn_attrs.target_features + .iter() + .map(|f| { + let feature = &*f.as_str(); + format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature)) + }) + ) .collect::>() .join(","); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 613a07cd269..148e3d0025c 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use attributes; use back::bytecode::{self, RLIB_BYTECODE_EXTENSION}; use back::lto::{self, ModuleBuffer, ThinBuffer}; use back::link::{self, get_linker, remove}; @@ -111,31 +112,6 @@ pub fn write_output_file( } } -// On android, we by default compile for armv7 processors. This enables -// things like double word CAS instructions (rather than emulating them) -// which are *far* more efficient. This is obviously undesirable in some -// cases, so if any sort of target feature is specified we don't append v7 -// to the feature list. -// -// On iOS only armv7 and newer are supported. So it is useful to -// get all hardware potential via VFP3 (hardware floating point) -// and NEON (SIMD) instructions supported by LLVM. -// Note that without those flags various linking errors might -// arise as some of intrinsics are converted into function calls -// and nobody provides implementations those functions -fn target_feature(sess: &Session) -> String { - let rustc_features = [ - "crt-static", - ]; - let requested_features = sess.opts.cg.target_feature.split(','); - let llvm_features = requested_features.filter(|f| { - !rustc_features.iter().any(|s| f.contains(s)) - }); - format!("{},{}", - sess.target.target.options.features, - llvm_features.collect::>().join(",")) -} - fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel { match optimize { config::OptLevel::No => llvm::CodeGenOptLevel::None, @@ -203,7 +179,10 @@ pub fn target_machine_factory(sess: &Session, find_features: bool) None => &*sess.target.target.options.cpu }; let cpu = CString::new(cpu.as_bytes()).unwrap(); - let features = CString::new(target_feature(sess).as_bytes()).unwrap(); + let features = attributes::llvm_target_features(sess) + .collect::>() + .join(","); + let features = CString::new(features).unwrap(); let is_pie_binary = !find_features && is_pie_binary(sess); let trap_unreachable = sess.target.target.options.trap_unreachable; diff --git a/src/test/codegen/target-feature-on-functions.rs b/src/test/codegen/target-feature-on-functions.rs new file mode 100644 index 00000000000..e3cc2c753e5 --- /dev/null +++ b/src/test/codegen/target-feature-on-functions.rs @@ -0,0 +1,19 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// only-x86_64 +// compile-flags: -C target-feature=+avx + +#![crate_type = "lib"] + +#[no_mangle] +pub fn foo() { + // CHECK: attributes #0 = { {{.*}}"target-features"="+avx"{{.*}} } +} -- cgit 1.4.1-3-g733a5 From 5b800c231f45fcd823a3e958bb942cd620ceb3e0 Mon Sep 17 00:00:00 2001 From: Björn Steinbrink Date: Wed, 3 Jan 2018 10:29:27 +0100 Subject: Don't force-enable frame pointers when generating debug info We apparently used to generate bad/incomplete debug info causing debuggers not to find symbols of stack allocated variables. This was somehow worked around by having frame pointers. With the current codegen, this seems no longer necessary, so we can remove the code that force-enables frame pointers whenever debug info is requested. Since certain situations, like profiling code profit from having frame pointers, we add a -Cforce-frame-pointers flag to always enable frame pointers. Fixes #11906 --- src/librustc/session/config.rs | 6 ++++++ src/librustc/session/mod.rs | 2 +- src/librustc_trans/attributes.rs | 2 -- src/test/codegen/force-frame-pointers.rs | 16 ++++++++++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 src/test/codegen/force-frame-pointers.rs (limited to 'src/test/codegen') diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 06922d986b3..023be789222 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1053,6 +1053,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, 2 = full debug info with variable and type information"), opt_level: Option = (None, parse_opt_string, [TRACKED], "optimize with possible levels 0-3, s, or z"), + force_frame_pointers: bool = (false, parse_bool, [TRACKED], + "force frame pointers to be used"), debug_assertions: Option = (None, parse_opt_bool, [TRACKED], "explicitly enable the cfg(debug_assertions) directive"), inline_threshold: Option = (None, parse_opt_uint, [TRACKED], @@ -2965,6 +2967,10 @@ mod tests { opts.cg.debuginfo = Some(0xba5eba11); assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + opts = reference.clone(); + opts.cg.force_frame_pointers = true; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + opts = reference.clone(); opts.cg.debug_assertions = Some(true); assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 37a6b2e79f7..45b7e2d1740 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -20,7 +20,7 @@ use lint::builtin::BuiltinLintDiagnostics; use middle::allocator::AllocatorKind; use middle::dependency_format; use session::search_paths::PathKind; -use session::config::{DebugInfoLevel, OutputType}; +use session::config::{OutputType}; use ty::tls; use util::nodemap::{FxHashSet}; use util::common::{duration_to_secs_str, ErrorReported}; diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs index f455c19cc0b..5baed57092d 100644 --- a/src/librustc_trans/attributes.rs +++ b/src/librustc_trans/attributes.rs @@ -69,8 +69,6 @@ pub fn naked(val: ValueRef, is_naked: bool) { } pub fn set_frame_pointer_elimination(cx: &CodegenCx, llfn: ValueRef) { - // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a - // parameter. if cx.sess().must_not_eliminate_frame_pointers() { llvm::AddFunctionAttrStringValue( llfn, llvm::AttributePlace::Function, diff --git a/src/test/codegen/force-frame-pointers.rs b/src/test/codegen/force-frame-pointers.rs new file mode 100644 index 00000000000..d40406a0476 --- /dev/null +++ b/src/test/codegen/force-frame-pointers.rs @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// compile-flags: -C no-prepopulate-passes -C force-frame-pointers + +#![crate_type="lib"] + +// CHECK: attributes #{{.*}} "no-frame-pointer-elim"="true" +pub fn foo() {} -- cgit 1.4.1-3-g733a5 From 09d2db4e963c6696f7c22386b6791e419ad75cfb Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Tue, 6 Mar 2018 20:27:19 +0200 Subject: Rework force-frame-pointer This reworks the force-frame-pointer PR to explicitly only consider the value of the flag if it is provided, and use a target default otherwise. Something that was tried but not kept was renaming the flag to `frame-pointer`, because for flag `frame-pointer=no`, there is no guarante, that LLVM will elide *all* the frame pointers; oposite of what the literal reading of the flag would suggest. --- src/librustc/session/config.rs | 6 +++--- src/librustc/session/mod.rs | 7 +++++-- src/test/codegen/force-frame-pointers.rs | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'src/test/codegen') diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 023be789222..59b40e9e2dc 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1053,8 +1053,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, 2 = full debug info with variable and type information"), opt_level: Option = (None, parse_opt_string, [TRACKED], "optimize with possible levels 0-3, s, or z"), - force_frame_pointers: bool = (false, parse_bool, [TRACKED], - "force frame pointers to be used"), + force_frame_pointers: Option = (None, parse_opt_bool, [TRACKED], + "force use of the frame pointers"), debug_assertions: Option = (None, parse_opt_bool, [TRACKED], "explicitly enable the cfg(debug_assertions) directive"), inline_threshold: Option = (None, parse_opt_uint, [TRACKED], @@ -2968,7 +2968,7 @@ mod tests { assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); opts = reference.clone(); - opts.cg.force_frame_pointers = true; + opts.cg.force_frame_pointers = Some(false); assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); opts = reference.clone(); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 45b7e2d1740..2ab72ba20bf 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -658,8 +658,11 @@ impl Session { } pub fn must_not_eliminate_frame_pointers(&self) -> bool { - self.opts.debuginfo != DebugInfoLevel::NoDebugInfo - || !self.target.target.options.eliminate_frame_pointer + if let Some(x) = self.opts.cg.force_frame_pointers { + x + } else { + !self.target.target.options.eliminate_frame_pointer + } } /// Returns the symbol name for the registrar function, diff --git a/src/test/codegen/force-frame-pointers.rs b/src/test/codegen/force-frame-pointers.rs index d40406a0476..f70e3667198 100644 --- a/src/test/codegen/force-frame-pointers.rs +++ b/src/test/codegen/force-frame-pointers.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. // -// compile-flags: -C no-prepopulate-passes -C force-frame-pointers +// compile-flags: -C no-prepopulate-passes -C force-frame-pointers=y #![crate_type="lib"] -- cgit 1.4.1-3-g733a5