From 41a7177d6a4f54b690b057fc17d213300da15d5d Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Fri, 20 Mar 2015 12:55:07 +0100 Subject: [PATCH 1/8] Update librustc's README.txt for some code changes and reformat it. --- src/librustc/README.txt | 102 +++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 49 deletions(-) diff --git a/src/librustc/README.txt b/src/librustc/README.txt index 9b364768208eb..31812e19aee86 100644 --- a/src/librustc/README.txt +++ b/src/librustc/README.txt @@ -16,17 +16,17 @@ Your concerns are probably the same as someone else's. The crates of rustc =================== -Rustc consists of four crates altogether: `libsyntax`, `librustc`, -`librustc_back`, and `librustc_trans` (the names and divisions are not -set in stone and may change; in general, a finer-grained division of -crates is preferable): +Rustc consists of a number of crates, including `libsyntax`, +`librustc`, `librustc_back`, `librustc_trans`, and `librustc_driver` +(the names and divisions are not set in stone and may change; +in general, a finer-grained division of crates is preferable): -- `libsyntax` contains those things concerned purely with syntax -- +- `libsyntax` contains those things concerned purely with syntax – that is, the AST, parser, pretty-printer, lexer, macro expander, and - utilities for traversing ASTs -- are in a separate crate called - "syntax", whose files are in ./../libsyntax, where . is the current - directory (that is, the parent directory of front/, middle/, back/, - and so on). + utilities for traversing ASTs – are in a separate crate called + "syntax", whose files are in `./../libsyntax`, where `.` is the + current directory (that is, the parent directory of front/, middle/, + back/, and so on). - `librustc` (the current directory) contains the high-level analysis passes, such as the type checker, borrow checker, and so forth. @@ -41,31 +41,35 @@ crates is preferable): of miscellany. In general it contains code that runs towards the end of the compilation process. +- `librustc_driver` invokes the compiler from `libsyntax`, then the + analysis phases from `librustc`, and finally the lowering and + codegen passes from `librustc_trans`. + Roughly speaking the "order" of the three crates is as follows: libsyntax -> librustc -> librustc_trans | | +-----------------+-------------------+ | - librustc_trans/driver + librustc_driver -Here the role of `librustc_trans/driver` is to invoke the compiler -from libsyntax, then the analysis phases from librustc, and finally -the lowering and codegen passes from librustc_trans. Modules in the rustc crate ========================== -The rustc crate itself consists of the following subdirectories +The rustc crate itself consists of the following submodules (mostly, but not entirely, in their own directories): -session - options and data that pertain to the compilation session as a whole -middle - middle-end: name resolution, typechecking, LLVM code - generation -metadata - encoder and decoder for data required by - separate compilation -util - ubiquitous types and helper functions -lib - bindings to LLVM +- session: options and data that pertain to the compilation session as + a whole +- middle: middle-end: name resolution, typechecking, LLVM code + generation +- metadata: encoder and decoder for data required by separate + compilation +- plugin: infrastructure for compiler plugins +- lint: infrastructure for compiler warnings +- util: ubiquitous types and helper functions +- lib: bindings to LLVM The entry-point for the compiler is main() in the librustc_trans crate. @@ -73,34 +77,34 @@ crate. The 3 central data structures: ------------------------------ -#1: ./../libsyntax/ast.rs defines the AST. The AST is treated as immutable - after parsing, but it depends on mutable context data structures - (mainly hash maps) to give it meaning. +1. `./../libsyntax/ast.rs` defines the AST. The AST is treated as + immutable after parsing, but it depends on mutable context data + structures (mainly hash maps) to give it meaning. - - Many -- though not all -- nodes within this data structure are - wrapped in the type `spanned`, meaning that the front-end has - marked the input coordinates of that node. The member .node is - the data itself, the member .span is the input location (file, - line, column; both low and high). + - Many – though not all – nodes within this data structure are + wrapped in the type `spanned`, meaning that the front-end has + marked the input coordinates of that node. The member `node` is + the data itself, the member `span` is the input location (file, + line, column; both low and high). - - Many other nodes within this data structure carry a - def_id. These nodes represent the 'target' of some name - reference elsewhere in the tree. When the AST is resolved, by - middle/resolve.rs, all names wind up acquiring a def that they - point to. So anything that can be pointed-to by a name winds - up with a def_id. + - Many other nodes within this data structure carry a + `def_id`. These nodes represent the 'target' of some name + reference elsewhere in the tree. When the AST is resolved, by + `middle/resolve.rs`, all names wind up acquiring a def that they + point to. So anything that can be pointed-to by a name winds + up with a `def_id`. -#2: middle/ty.rs defines the datatype sty. This is the type that - represents types after they have been resolved and normalized by - the middle-end. The typeck phase converts every ast type to a - ty::sty, and the latter is used to drive later phases of - compilation. Most variants in the ast::ty tag have a - corresponding variant in the ty::sty tag. +2. `middle/ty.rs` defines the datatype `sty`. This is the type that + represents types after they have been resolved and normalized by + the middle-end. The typeck phase converts every ast type to a + `ty::sty`, and the latter is used to drive later phases of + compilation. Most variants in the `ast::ty` tag have a + corresponding variant in the `ty::sty` tag. -#3: lib/llvm.rs (in librustc_trans) defines the exported types - ValueRef, TypeRef, BasicBlockRef, and several others. Each of - these is an opaque pointer to an LLVM type, manipulated through - the lib::llvm interface. +3. `./../librustc_llvm/lib.rs` defines the exported types + `ValueRef`, `TypeRef`, `BasicBlockRef`, and several others. + Each of these is an opaque pointer to an LLVM type, + manipulated through the `lib::llvm` interface. Control and information flow within the compiler: @@ -109,10 +113,10 @@ Control and information flow within the compiler: - main() in lib.rs assumes control on startup. Options are parsed, platform is detected, etc. -- ./../libsyntax/parse/parser.rs parses the input files and produces an AST - that represents the input crate. +- `./../libsyntax/parse/parser.rs` parses the input files and produces + an AST that represents the input crate. -- Multiple middle-end passes (middle/resolve.rs, middle/typeck.rs) +- Multiple middle-end passes (`middle/resolve.rs`, `middle/typeck.rs`) analyze the semantics of the resulting AST. Each pass generates new information about the AST and stores it in various environment data structures. The driver passes environments to each compiler pass @@ -121,4 +125,4 @@ Control and information flow within the compiler: - Finally, the `trans` module in `librustc_trans` translates the Rust AST to LLVM bitcode in a type-directed way. When it's finished synthesizing LLVM values, rustc asks LLVM to write them out in some - form (.bc, .o) and possibly run the system linker. + form (`.bc`, `.o`) and possibly run the system linker. From 3bdb5c3078a69becbf249739c8099ac9acb3513d Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Fri, 20 Mar 2015 13:28:06 +0100 Subject: [PATCH 2/8] Make librustc's markdown README.txt claim to be markdown. This allows github to render it with formatting. --- src/librustc/{README.txt => README.md} | 0 src/librustc_trans/README.txt | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/librustc/{README.txt => README.md} (100%) diff --git a/src/librustc/README.txt b/src/librustc/README.md similarity index 100% rename from src/librustc/README.txt rename to src/librustc/README.md diff --git a/src/librustc_trans/README.txt b/src/librustc_trans/README.txt index 3904db4433c89..1f416d5404d27 100644 --- a/src/librustc_trans/README.txt +++ b/src/librustc_trans/README.txt @@ -1 +1 @@ -See the README.txt in ../librustc. +See the README.md in ../librustc. From 8f0de740f8a5a21a9c07552ae89654412382b9f3 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Fri, 20 Mar 2015 10:53:47 -0400 Subject: [PATCH 3/8] environment variables -> environment As @sanxiyn says, https://github.com/rust-lang/rust/pull/23527#issuecomment-83835448 --- man/rustc.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/rustc.1 b/man/rustc.1 index 33ef3f9ee4acb..b15829db431df 100644 --- a/man/rustc.1 +++ b/man/rustc.1 @@ -242,7 +242,7 @@ full debug info with variable and type information. \fBopt\-level\fR=\fIVAL\fR Optimize with possible levels 0\[en]3 -.SH ENVIRONMENT VARIABLES +.SH ENVIRONMENT Some of these affect the output of the compiler, while others affect programs which link to the standard library. From 5fe0bb743a0af0413f8989a70a4f926fa5c63074 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Fri, 20 Mar 2015 10:22:57 -0700 Subject: [PATCH 4/8] Future-proof indexing on maps: remove IndexMut This commit removes the `IndexMut` impls on `HashMap` and `BTreeMap`, in order to future-proof the API against the eventual inclusion of an `IndexSet` trait. Ideally, we would eventually be able to support: ```rust map[owned_key] = val; map[borrowed_key].mutating_method(arguments); &mut map[borrowed_key]; ``` but to keep the design space as unconstrained as possible, we do not currently want to support `IndexMut`, in case some other strategy will eventually be needed. Code currently using mutating index notation can use `get_mut` instead. [breaking-change] Closes #23448 --- src/libcollections/btree/map.rs | 11 +---------- src/librustc_resolve/lib.rs | 2 +- src/librustc_resolve/resolve_imports.rs | 2 +- src/librustc_typeck/check/upvar.rs | 2 +- src/libstd/collections/hash/map.rs | 14 +------------- 5 files changed, 5 insertions(+), 26 deletions(-) diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index c7e1e3c91766e..a9e1ce8d7ce50 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -24,7 +24,7 @@ use core::default::Default; use core::fmt::Debug; use core::hash::{Hash, Hasher}; use core::iter::{Map, FromIterator, IntoIterator}; -use core::ops::{Index, IndexMut}; +use core::ops::{Index}; use core::{iter, fmt, mem, usize}; use Bound::{self, Included, Excluded, Unbounded}; @@ -925,15 +925,6 @@ impl Index for BTreeMap } } -#[stable(feature = "rust1", since = "1.0.0")] -impl IndexMut for BTreeMap - where K: Borrow, Q: Ord -{ - fn index_mut(&mut self, key: &Q) -> &mut V { - self.get_mut(key).expect("no entry found for key") - } -} - /// Genericises over how to get the correct type of iterator from the correct type /// of Node ownership. trait Traverse { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b619c6a77d009..566af2590e6c0 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -900,7 +900,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return; } if self.glob_map.contains_key(&import_id) { - self.glob_map[import_id].insert(name); + self.glob_map.get_mut(&import_id).unwrap().insert(name); return; } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 737ec71cab3da..46451019760dd 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -603,7 +603,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { // We've successfully resolved the import. Write the results in. let mut import_resolutions = module_.import_resolutions.borrow_mut(); - let import_resolution = &mut (*import_resolutions)[target]; + let import_resolution = import_resolutions.get_mut(&target).unwrap(); { let mut check_and_write_import = |namespace, result: &_, used_public: &mut bool| { diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 09592db8a116d..ce4bb4465517b 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -380,7 +380,7 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> { // borrow_kind of the upvar to make sure it // is inferred to mutable if necessary let mut upvar_capture_map = self.fcx.inh.upvar_capture_map.borrow_mut(); - let ub = &mut upvar_capture_map[upvar_id]; + let ub = upvar_capture_map.get_mut(&upvar_id).unwrap(); self.adjust_upvar_borrow_kind(upvar_id, ub, borrow_kind); // also need to be in an FnMut closure since this is not an ImmBorrow diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 60b1738d2c989..9139e182ce479 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -23,7 +23,7 @@ use hash::{Hash, SipHasher}; use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map}; use marker::Sized; use mem::{self, replace}; -use ops::{Deref, FnMut, Index, IndexMut}; +use ops::{Deref, FnMut, Index}; use option::Option::{self, Some, None}; use rand::{self, Rng}; use result::Result::{self, Ok, Err}; @@ -1258,18 +1258,6 @@ impl Index for HashMap } } -#[stable(feature = "rust1", since = "1.0.0")] -impl IndexMut for HashMap - where K: Eq + Hash + Borrow, - Q: Eq + Hash, - S: HashState, -{ - #[inline] - fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V { - self.get_mut(index).expect("no entry found for key") - } -} - /// HashMap iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, K: 'a, V: 'a> { From 9acdcba3d5e6901e6a91e28f86420c8014a28328 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Fri, 20 Mar 2015 15:26:26 -0400 Subject: [PATCH 5/8] Remove manual numbers from TRPL Rustbook already does this. --- src/doc/trpl/SUMMARY.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index 6ff51e8d1b92c..76f8b6c973818 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -1,6 +1,6 @@ # Summary -* [I: The Basics](basic.md) +* [The Basics](basic.md) * [Installing Rust](installing-rust.md) * [Hello, world!](hello-world.md) * [Hello, Cargo!](hello-cargo.md) @@ -14,7 +14,7 @@ * [Strings](strings.md) * [Arrays, Vectors, and Slices](arrays-vectors-and-slices.md) * [Standard Input](standard-input.md) -* [II: Intermediate Rust](intermediate.md) +* [Intermediate Rust](intermediate.md) * [Crates and Modules](crates-and-modules.md) * [Testing](testing.md) * [Pointers](pointers.md) @@ -31,7 +31,7 @@ * [Concurrency](concurrency.md) * [Error Handling](error-handling.md) * [Documentation](documentation.md) -* [III: Advanced Topics](advanced.md) +* [Advanced Topics](advanced.md) * [FFI](ffi.md) * [Unsafe Code](unsafe.md) * [Advanced Macros](advanced-macros.md) From 84b14c5dc9bceeadb24beaa5ae1b126701b7d932 Mon Sep 17 00:00:00 2001 From: Barosl Lee Date: Sat, 21 Mar 2015 14:38:23 +0900 Subject: [PATCH 6/8] Fix documentation for std::sync::mutex: into_guard -> into_inner --- src/libstd/sync/mutex.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 1cbfbbf29278f..130fd1d7dc83b 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -40,7 +40,7 @@ use fmt; /// among threads to ensure that a possibly invalid invariant is not witnessed. /// /// A poisoned mutex, however, does not prevent all access to the underlying -/// data. The `PoisonError` type has an `into_guard` method which will return +/// data. The `PoisonError` type has an `into_inner` method which will return /// the guard that would have otherwise been returned on a successful lock. This /// allows access to the data, despite the lock being poisoned. /// @@ -105,7 +105,7 @@ use fmt; /// // pattern matched on to return the underlying guard on both branches. /// let mut guard = match lock.lock() { /// Ok(guard) => guard, -/// Err(poisoned) => poisoned.into_guard(), +/// Err(poisoned) => poisoned.into_inner(), /// }; /// /// *guard += 1; From c48bb85702aaf8966b0d1c050a7152dce5ac6afa Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sat, 21 Mar 2015 00:23:39 +0100 Subject: [PATCH 7/8] Add tests checking that a number of feature gates are gating their features. Namely: * `box_syntax` * `box_patterns` * `simd_ffi` * `macro_reexport` cc #22820 --- .../gated-macro-reexports.rs | 22 +++++++++++++++ src/test/compile-fail/gated-box-patterns.rs | 22 +++++++++++++++ src/test/compile-fail/gated-box-syntax.rs | 17 ++++++++++++ src/test/compile-fail/gated-simd-ffi.rs | 27 +++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 src/test/compile-fail-fulldeps/gated-macro-reexports.rs create mode 100644 src/test/compile-fail/gated-box-patterns.rs create mode 100644 src/test/compile-fail/gated-box-syntax.rs create mode 100644 src/test/compile-fail/gated-simd-ffi.rs diff --git a/src/test/compile-fail-fulldeps/gated-macro-reexports.rs b/src/test/compile-fail-fulldeps/gated-macro-reexports.rs new file mode 100644 index 0000000000000..a88445bafc049 --- /dev/null +++ b/src/test/compile-fail-fulldeps/gated-macro-reexports.rs @@ -0,0 +1,22 @@ +// Copyright 2014 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. + +// Test that macro reexports item are gated by `macro_reexport` feature gate. + +// aux-build:macro_reexport_1.rs +// ignore-stage1 + +#![crate_type = "dylib"] + +#[macro_reexport(reexported)] +#[macro_use] #[no_link] +extern crate macro_reexport_1; +//~^ ERROR macros reexports are experimental and possibly buggy +//~| HELP add #![feature(macro_reexport)] to the crate attributes to enable diff --git a/src/test/compile-fail/gated-box-patterns.rs b/src/test/compile-fail/gated-box-patterns.rs new file mode 100644 index 0000000000000..abaa256d52e7f --- /dev/null +++ b/src/test/compile-fail/gated-box-patterns.rs @@ -0,0 +1,22 @@ +// Copyright 2015 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. + +// Test that patterns including the box syntax are gated by `box_patterns` feature gate. + +fn main() { + let x = Box::new(1); + + match x { + box 1 => (), + //~^ box pattern syntax is experimental + //~| add #![feature(box_patterns)] to the crate attributes to enable + _ => () + }; +} diff --git a/src/test/compile-fail/gated-box-syntax.rs b/src/test/compile-fail/gated-box-syntax.rs new file mode 100644 index 0000000000000..3e08c1f7a7130 --- /dev/null +++ b/src/test/compile-fail/gated-box-syntax.rs @@ -0,0 +1,17 @@ +// Copyright 2015 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. + +// Test that the use of the box syntax is gated by `box_syntax` feature gate. + +fn main() { + let x = box 3; + //~^ ERROR box expression syntax is experimental; you can call `Box::new` instead. + //~| HELP add #![feature(box_syntax)] to the crate attributes to enable +} diff --git a/src/test/compile-fail/gated-simd-ffi.rs b/src/test/compile-fail/gated-simd-ffi.rs new file mode 100644 index 0000000000000..c0a251e77a316 --- /dev/null +++ b/src/test/compile-fail/gated-simd-ffi.rs @@ -0,0 +1,27 @@ +// Copyright 2015 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. + +// Test that the use of smid types in the ffi is gated by `smid_ffi` feature gate. + +#![feature(simd)] + +#[repr(C)] +#[derive(Copy)] +#[simd] +pub struct f32x4(f32, f32, f32, f32); + +#[allow(dead_code)] +extern { + fn foo(x: f32x4); + //~^ ERROR use of SIMD type `f32x4` in FFI is highly experimental and may result in invalid code + //~| HELP add #![feature(simd_ffi)] to the crate attributes to enable +} + +fn main() {} From d4ca1cffce6f948e190c5910f5b08771bf30ca59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Sat, 21 Mar 2015 00:21:38 +0100 Subject: [PATCH 8/8] Fix volatile / atomic ops on bools and small aggregates Boolean values and small aggregates have a different type in args/allocas than in SSA values but the intrinsics for volatile and atomic ops were missing the necessary casts to handle that. Fixes #23550 --- src/librustc_trans/trans/base.rs | 92 ++++++++++++++++----------- src/librustc_trans/trans/intrinsic.rs | 30 +++++++-- src/test/run-pass/issue-23550.rs | 39 ++++++++++++ 3 files changed, 116 insertions(+), 45 deletions(-) create mode 100644 src/test/run-pass/issue-23550.rs diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index f584de7c47f3b..ebd92faaf0f53 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -983,56 +983,72 @@ pub fn load_if_immediate<'blk, 'tcx>(cx: Block<'blk, 'tcx>, /// gives us better information about what we are loading. pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ptr: ValueRef, t: Ty<'tcx>) -> ValueRef { - if type_is_zero_size(cx.ccx(), t) { - C_undef(type_of::type_of(cx.ccx(), t)) - } else if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() { - // We want to pass small aggregates as immediate values, but using an aggregate LLVM type - // for this leads to bad optimizations, so its arg type is an appropriately sized integer - // and we have to convert it - Load(cx, BitCast(cx, ptr, type_of::arg_type_of(cx.ccx(), t).ptr_to())) - } else { - unsafe { - let global = llvm::LLVMIsAGlobalVariable(ptr); - if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True { - let val = llvm::LLVMGetInitializer(global); - if !val.is_null() { - // This could go into its own function, for DRY. - // (something like "pre-store packing/post-load unpacking") - if ty::type_is_bool(t) { - return Trunc(cx, val, Type::i1(cx.ccx())); - } else { - return val; - } - } + if cx.unreachable.get() || type_is_zero_size(cx.ccx(), t) { + return C_undef(type_of::type_of(cx.ccx(), t)); + } + + let ptr = to_arg_ty_ptr(cx, ptr, t); + + if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() { + return Load(cx, ptr); + } + + unsafe { + let global = llvm::LLVMIsAGlobalVariable(ptr); + if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True { + let val = llvm::LLVMGetInitializer(global); + if !val.is_null() { + return from_arg_ty(cx, val, t); } } - if ty::type_is_bool(t) { - Trunc(cx, LoadRangeAssert(cx, ptr, 0, 2, llvm::False), Type::i1(cx.ccx())) - } else if ty::type_is_char(t) { - // a char is a Unicode codepoint, and so takes values from 0 - // to 0x10FFFF inclusive only. - LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, llvm::False) - } else if (ty::type_is_region_ptr(t) || ty::type_is_unique(t)) - && !common::type_is_fat_ptr(cx.tcx(), t) { - LoadNonNull(cx, ptr) - } else { - Load(cx, ptr) - } } + + let val = if ty::type_is_bool(t) { + LoadRangeAssert(cx, ptr, 0, 2, llvm::False) + } else if ty::type_is_char(t) { + // a char is a Unicode codepoint, and so takes values from 0 + // to 0x10FFFF inclusive only. + LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, llvm::False) + } else if (ty::type_is_region_ptr(t) || ty::type_is_unique(t)) + && !common::type_is_fat_ptr(cx.tcx(), t) { + LoadNonNull(cx, ptr) + } else { + Load(cx, ptr) + }; + + from_arg_ty(cx, val, t) } /// Helper for storing values in memory. Does the necessary conversion if the in-memory type /// differs from the type used for SSA values. pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t: Ty<'tcx>) { - if ty::type_is_bool(t) { - Store(cx, ZExt(cx, v, Type::i8(cx.ccx())), dst); - } else if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() { + Store(cx, to_arg_ty(cx, v, t), to_arg_ty_ptr(cx, dst, t)); +} + +pub fn to_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef { + if ty::type_is_bool(ty) { + ZExt(bcx, val, Type::i8(bcx.ccx())) + } else { + val + } +} + +pub fn from_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef { + if ty::type_is_bool(ty) { + Trunc(bcx, val, Type::i1(bcx.ccx())) + } else { + val + } +} + +pub fn to_arg_ty_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ptr: ValueRef, ty: Ty<'tcx>) -> ValueRef { + if type_is_immediate(bcx.ccx(), ty) && type_of::type_of(bcx.ccx(), ty).is_aggregate() { // We want to pass small aggregates as immediate values, but using an aggregate LLVM type // for this leads to bad optimizations, so its arg type is an appropriately sized integer // and we have to convert it - Store(cx, v, BitCast(cx, dst, type_of::arg_type_of(cx.ccx(), t).ptr_to())); + BitCast(bcx, ptr, type_of::arg_type_of(bcx.ccx(), ty).ptr_to()) } else { - Store(cx, v, dst); + ptr } } diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index 69ca9a5e81cbc..d158cfa7b8876 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -446,10 +446,15 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, call_debug_location) } (_, "volatile_load") => { - VolatileLoad(bcx, llargs[0]) + let tp_ty = *substs.types.get(FnSpace, 0); + let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty); + from_arg_ty(bcx, VolatileLoad(bcx, ptr), tp_ty) }, (_, "volatile_store") => { - VolatileStore(bcx, llargs[1], llargs[0]); + let tp_ty = *substs.types.get(FnSpace, 0); + let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty); + let val = to_arg_ty(bcx, llargs[1], tp_ty); + VolatileStore(bcx, val, ptr); C_nil(ccx) }, @@ -709,8 +714,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, llvm::SequentiallyConsistent }; - let res = AtomicCmpXchg(bcx, llargs[0], llargs[1], - llargs[2], order, + let tp_ty = *substs.types.get(FnSpace, 0); + let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty); + let cmp = to_arg_ty(bcx, llargs[1], tp_ty); + let src = to_arg_ty(bcx, llargs[2], tp_ty); + let res = AtomicCmpXchg(bcx, ptr, cmp, src, order, strongest_failure_ordering); if unsafe { llvm::LLVMVersionMinor() >= 5 } { ExtractValue(bcx, res, 0) @@ -720,10 +728,15 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } "load" => { - AtomicLoad(bcx, llargs[0], order) + let tp_ty = *substs.types.get(FnSpace, 0); + let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty); + from_arg_ty(bcx, AtomicLoad(bcx, ptr, order), tp_ty) } "store" => { - AtomicStore(bcx, llargs[1], llargs[0], order); + let tp_ty = *substs.types.get(FnSpace, 0); + let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty); + let val = to_arg_ty(bcx, llargs[1], tp_ty); + AtomicStore(bcx, val, ptr, order); C_nil(ccx) } @@ -749,7 +762,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, _ => ccx.sess().fatal("unknown atomic operation") }; - AtomicRMW(bcx, atom_op, llargs[0], llargs[1], order) + let tp_ty = *substs.types.get(FnSpace, 0); + let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty); + let val = to_arg_ty(bcx, llargs[1], tp_ty); + AtomicRMW(bcx, atom_op, ptr, val, order) } } diff --git a/src/test/run-pass/issue-23550.rs b/src/test/run-pass/issue-23550.rs new file mode 100644 index 0000000000000..97357c1dba467 --- /dev/null +++ b/src/test/run-pass/issue-23550.rs @@ -0,0 +1,39 @@ +// Copyright 2015 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. + +#![feature(core)] +#![allow(warnings)] + +use std::intrinsics; + +#[derive(Copy)] +struct Wrap(i64); + +// These volatile and atomic intrinsics used to cause an ICE + +unsafe fn test_bool(p: &mut bool, v: bool) { + intrinsics::volatile_load(p); + intrinsics::volatile_store(p, v); + intrinsics::atomic_load(p); + intrinsics::atomic_cxchg(p, v, v); + intrinsics::atomic_store(p, v); + intrinsics::atomic_xchg(p, v); +} + +unsafe fn test_immediate_fca(p: &mut Wrap, v: Wrap) { + intrinsics::volatile_load(p); + intrinsics::volatile_store(p, v); + intrinsics::atomic_load(p); + intrinsics::atomic_cxchg(p, v, v); + intrinsics::atomic_store(p, v); + intrinsics::atomic_xchg(p, v); +} + +fn main() {}