Skip to content

Commit

Permalink
Auto merge of rust-lang#74642 - Manishearth:rollup-148kz52, r=Manishe…
Browse files Browse the repository at this point in the history
…arth

Rollup of 9 pull requests

Successful merges:

 - rust-lang#73655 (va_args implementation for AAPCS.)
 - rust-lang#73893 (Stabilize control-flow-guard codegen option)
 - rust-lang#74237 (compiletest: Rewrite extract_*_version functions)
 - rust-lang#74454 (small coherence cleanup)
 - rust-lang#74528 (refactor and reword intra-doc link errors)
 - rust-lang#74568 (Apply rust-lang#66379 to `*mut T` `as_ref`)
 - rust-lang#74570 (Use forge links for prioritization procedure)
 - rust-lang#74589 (Update books)
 - rust-lang#74635 (Fix tooltip position if the documentation starts with a code block)

Failed merges:

r? @ghost
  • Loading branch information
bors committed Jul 22, 2020
2 parents 69d68f9 + 05a2466 commit 9e92106
Show file tree
Hide file tree
Showing 53 changed files with 751 additions and 635 deletions.
2 changes: 1 addition & 1 deletion src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1239,7 +1239,7 @@ impl<'a> Builder<'a> {
&& self.config.control_flow_guard
&& compiler.stage >= 1
{
rustflags.arg("-Zcontrol-flow-guard");
rustflags.arg("-Ccontrol-flow-guard");
}

// For `cargo doc` invocations, make rustdoc print the Rust version into the docs
Expand Down
2 changes: 1 addition & 1 deletion src/doc/book
12 changes: 12 additions & 0 deletions src/doc/rustc/src/codegen-options/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ generated code, but may be slower to compile.
The default value, if not specified, is 16 for non-incremental builds. For
incremental builds the default is 256 which allows caching to be more granular.

## control-flow-guard

This flag controls whether LLVM enables the Windows [Control Flow
Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard)
platform security feature. This flag is currently ignored for non-Windows targets.
It takes one of the following values:

* `y`, `yes`, `on`, `checks`, or no value: enable Control Flow Guard.
* `nochecks`: emit Control Flow Guard metadata without runtime enforcement checks (this
should only be used for testing purposes as it does not provide security enforcement).
* `n`, `no`, `off`: do not enable Control Flow Guard (the default).

## debug-assertions

This flag lets you turn `cfg(debug_assertions)` [conditional
Expand Down
19 changes: 12 additions & 7 deletions src/libcore/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,22 @@ impl<T: ?Sized> *mut T {
/// operation because the returned value could be pointing to invalid
/// memory.
///
/// When calling this method, you have to ensure that if the pointer is
/// non-NULL, then it is properly aligned, dereferenceable (for the whole
/// size of `T`) and points to an initialized instance of `T`. This applies
/// even if the result of this method is unused!
/// When calling this method, you have to ensure that *either* the pointer is NULL *or*
/// all of the following is true:
/// - it is properly aligned
/// - it must point to an initialized instance of T; in particular, the pointer must be
/// "dereferencable" in the sense defined [here].
///
/// This applies even if the result of this method is unused!
/// (The part about being initialized is not yet fully decided, but until
/// it is, the only safe approach is to ensure that they are indeed initialized.)
///
/// Additionally, the lifetime `'a` returned is arbitrarily chosen and does
/// not necessarily reflect the actual lifetime of the data. It is up to the
/// caller to ensure that for the duration of this lifetime, the memory this
/// pointer points to does not get written to outside of `UnsafeCell<U>`.
/// not necessarily reflect the actual lifetime of the data. *You* must enforce
/// Rust's aliasing rules. In particular, for the duration of this lifetime,
/// the memory the pointer points to must not get mutated (except inside `UnsafeCell`).
///
/// [here]: crate::ptr#safety
///
/// # Examples
///
Expand Down
7 changes: 6 additions & 1 deletion src/librustc_codegen_llvm/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1330,7 +1330,12 @@ impl Builder<'a, 'll, 'tcx> {
self.call(lifetime_intrinsic, &[self.cx.const_u64(size), ptr], None);
}

fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
pub(crate) fn phi(
&mut self,
ty: &'ll Type,
vals: &[&'ll Value],
bbs: &[&'ll BasicBlock],
) -> &'ll Value {
assert_eq!(vals.len(), bbs.len());
let phi = unsafe { llvm::LLVMBuildPhi(self.llbuilder, ty, UNNAMED) };
unsafe {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_llvm/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ pub unsafe fn create_module(

// Control Flow Guard is currently only supported by the MSVC linker on Windows.
if sess.target.target.options.is_like_msvc {
match sess.opts.debugging_opts.control_flow_guard {
match sess.opts.cg.control_flow_guard {
CFGuard::Disabled => {}
CFGuard::NoChecks => {
// Set `cfguard=1` module flag to emit metadata only.
Expand Down
81 changes: 79 additions & 2 deletions src/librustc_codegen_llvm/va_arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
use rustc_codegen_ssa::mir::operand::OperandRef;
use rustc_codegen_ssa::traits::{
BaseTypeMethods, BuilderMethods, ConstMethods, DerivedTypeMethods,
use rustc_codegen_ssa::{
common::IntPredicate,
traits::{BaseTypeMethods, BuilderMethods, ConstMethods, DerivedTypeMethods},
};
use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::Ty;
Expand Down Expand Up @@ -89,6 +90,81 @@ fn emit_ptr_va_arg(
}
}

fn emit_aapcs_va_arg(
bx: &mut Builder<'a, 'll, 'tcx>,
list: OperandRef<'tcx, &'ll Value>,
target_ty: Ty<'tcx>,
) -> &'ll Value {
// Implementation of the AAPCS64 calling convention for va_args see
// https://github.com/ARM-software/abi-aa/blob/master/aapcs64/aapcs64.rst
let va_list_addr = list.immediate();
let layout = bx.cx.layout_of(target_ty);

let mut maybe_reg = bx.build_sibling_block("va_arg.maybe_reg");
let mut in_reg = bx.build_sibling_block("va_arg.in_reg");
let mut on_stack = bx.build_sibling_block("va_arg.on_stack");
let mut end = bx.build_sibling_block("va_arg.end");
let zero = bx.const_i32(0);
let offset_align = Align::from_bytes(4).unwrap();
assert!(&*bx.tcx().sess.target.target.target_endian == "little");

let gr_type = target_ty.is_any_ptr() || target_ty.is_integral();
let (reg_off, reg_top_index, slot_size) = if gr_type {
let gr_offs = bx.struct_gep(va_list_addr, 7);
let nreg = (layout.size.bytes() + 7) / 8;
(gr_offs, 3, nreg * 8)
} else {
let vr_off = bx.struct_gep(va_list_addr, 9);
let nreg = (layout.size.bytes() + 15) / 16;
(vr_off, 5, nreg * 16)
};

// if the offset >= 0 then the value will be on the stack
let mut reg_off_v = bx.load(reg_off, offset_align);
let use_stack = bx.icmp(IntPredicate::IntSGE, reg_off_v, zero);
bx.cond_br(use_stack, &on_stack.llbb(), &maybe_reg.llbb());

// The value at this point might be in a register, but there is a chance that
// it could be on the stack so we have to update the offset and then check
// the offset again.

if gr_type && layout.align.abi.bytes() > 8 {
reg_off_v = maybe_reg.add(reg_off_v, bx.const_i32(15));
reg_off_v = maybe_reg.and(reg_off_v, bx.const_i32(-16));
}
let new_reg_off_v = maybe_reg.add(reg_off_v, bx.const_i32(slot_size as i32));

maybe_reg.store(new_reg_off_v, reg_off, offset_align);

// Check to see if we have overflowed the registers as a result of this.
// If we have then we need to use the stack for this value
let use_stack = maybe_reg.icmp(IntPredicate::IntSGT, new_reg_off_v, zero);
maybe_reg.cond_br(use_stack, &on_stack.llbb(), &in_reg.llbb());

let top = in_reg.struct_gep(va_list_addr, reg_top_index);
let top = in_reg.load(top, bx.tcx().data_layout.pointer_align.abi);

// reg_value = *(@top + reg_off_v);
let top = in_reg.gep(top, &[reg_off_v]);
let top = in_reg.bitcast(top, bx.cx.type_ptr_to(layout.llvm_type(bx)));
let reg_value = in_reg.load(top, layout.align.abi);
in_reg.br(&end.llbb());

// On Stack block
let stack_value =
emit_ptr_va_arg(&mut on_stack, list, target_ty, false, Align::from_bytes(8).unwrap(), true);
on_stack.br(&end.llbb());

let val = end.phi(
layout.immediate_llvm_type(bx),
&[reg_value, stack_value],
&[&in_reg.llbb(), &on_stack.llbb()],
);

*bx = end;
val
}

pub(super) fn emit_va_arg(
bx: &mut Builder<'a, 'll, 'tcx>,
addr: OperandRef<'tcx, &'ll Value>,
Expand All @@ -115,6 +191,7 @@ pub(super) fn emit_va_arg(
("aarch64", _) if target.target_os == "ios" => {
emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), true)
}
("aarch64", _) => emit_aapcs_va_arg(bx, addr, target_ty),
// Windows x86_64
("x86_64", true) => {
let target_ty_size = bx.cx.size_of(target_ty).bytes();
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_ssa/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1700,7 +1700,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
}

// OBJECT-FILES-NO, AUDIT-ORDER
if sess.opts.debugging_opts.control_flow_guard != CFGuard::Disabled {
if sess.opts.cg.control_flow_guard != CFGuard::Disabled {
cmd.control_flow_guard();
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_interface/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ fn test_codegen_options_tracking_hash() {
// Make sure that changing a [TRACKED] option changes the hash.
// This list is in alphabetical order.
tracked!(code_model, Some(CodeModel::Large));
tracked!(control_flow_guard, CFGuard::Checks);
tracked!(debug_assertions, Some(true));
tracked!(debuginfo, 0xdeadbeef);
tracked!(embed_bitcode, false);
Expand Down Expand Up @@ -537,7 +538,6 @@ fn test_debugging_options_tracking_hash() {
tracked!(binary_dep_depinfo, true);
tracked!(chalk, true);
tracked!(codegen_backend, Some("abc".to_string()));
tracked!(control_flow_guard, CFGuard::Checks);
tracked!(crate_attr, vec!["abc".to_string()]);
tracked!(debug_macros, true);
tracked!(dep_info_omit_d_target, true);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ pub enum Strip {
Symbols,
}

/// The different settings that the `-Z control-flow-guard` flag can have.
/// The different settings that the `-C control-flow-guard` flag can have.
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
pub enum CFGuard {
/// Do not emit Control Flow Guard metadata or checks.
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_session/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
"choose the code model to use (`rustc --print code-models` for details)"),
codegen_units: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
"divide crate into N units to optimize in parallel"),
control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED],
"use Windows Control Flow Guard (default: no)"),
debug_assertions: Option<bool> = (None, parse_opt_bool, [TRACKED],
"explicitly enable the `cfg(debug_assertions)` directive"),
debuginfo: usize = (0, parse_uint, [TRACKED],
Expand Down Expand Up @@ -809,8 +811,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"enable the experimental Chalk-based trait solving engine"),
codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
"the backend to use"),
control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED],
"use Windows Control Flow Guard (default: no)"),
crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
"inject the given attribute in the crate"),
debug_macros: bool = (false, parse_bool, [TRACKED],
Expand Down
Loading

0 comments on commit 9e92106

Please sign in to comment.