Skip to content

Commit 600dc35

Browse files
committedApr 4, 2016
Auto merge of #32647 - Amanieu:checked_atomic_intrinsics, r=eddyb
Only allow using the atomic intrinsics on integer types Using these with non-integer types results in LLVM asserts. Atomic operations on non-integer types will require values be transmuted into an integer type of suitable size. This doesn't affect the standard library since `AtomicBool` and `AtomicPtr` currently use `usize` for atomic operations. r? @eddyb
2 parents 8d5e845 + 8620bba commit 600dc35

File tree

3 files changed

+161
-31
lines changed

3 files changed

+161
-31
lines changed
 

‎src/librustc_trans/intrinsic.rs

+43-22
Original file line numberDiff line numberDiff line change
@@ -752,33 +752,47 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
752752

753753
match split[1] {
754754
"cxchg" | "cxchgweak" => {
755-
let cmp = from_immediate(bcx, llargs[1]);
756-
let src = from_immediate(bcx, llargs[2]);
757-
let ptr = PointerCast(bcx, llargs[0], val_ty(src).ptr_to());
758-
let weak = if split[1] == "cxchgweak" { llvm::True } else { llvm::False };
759-
let val = AtomicCmpXchg(bcx, ptr, cmp, src, order, failorder, weak);
760-
let result = ExtractValue(bcx, val, 0);
761-
let success = ZExt(bcx, ExtractValue(bcx, val, 1), Type::bool(bcx.ccx()));
762-
Store(bcx,
763-
result,
764-
PointerCast(bcx, StructGEP(bcx, llresult, 0), val_ty(src).ptr_to()));
765-
Store(bcx, success, StructGEP(bcx, llresult, 1));
755+
let sty = &substs.types.get(FnSpace, 0).sty;
756+
if int_type_width_signed(sty, ccx).is_some() {
757+
let weak = if split[1] == "cxchgweak" { llvm::True } else { llvm::False };
758+
let val = AtomicCmpXchg(bcx, llargs[0], llargs[1], llargs[2],
759+
order, failorder, weak);
760+
let result = ExtractValue(bcx, val, 0);
761+
let success = ZExt(bcx, ExtractValue(bcx, val, 1), Type::bool(bcx.ccx()));
762+
Store(bcx, result, StructGEP(bcx, llresult, 0));
763+
Store(bcx, success, StructGEP(bcx, llresult, 1));
764+
} else {
765+
span_invalid_monomorphization_error(
766+
tcx.sess, span,
767+
&format!("invalid monomorphization of `{}` intrinsic: \
768+
expected basic integer type, found `{}`", name, sty));
769+
}
766770
C_nil(ccx)
767771
}
768772

769773
"load" => {
770-
let tp_ty = *substs.types.get(FnSpace, 0);
771-
let mut ptr = llargs[0];
772-
if let Some(ty) = fn_ty.ret.cast {
773-
ptr = PointerCast(bcx, ptr, ty.ptr_to());
774+
let sty = &substs.types.get(FnSpace, 0).sty;
775+
if int_type_width_signed(sty, ccx).is_some() {
776+
AtomicLoad(bcx, llargs[0], order)
777+
} else {
778+
span_invalid_monomorphization_error(
779+
tcx.sess, span,
780+
&format!("invalid monomorphization of `{}` intrinsic: \
781+
expected basic integer type, found `{}`", name, sty));
782+
C_nil(ccx)
774783
}
775-
to_immediate(bcx, AtomicLoad(bcx, ptr, order), tp_ty)
776784
}
777785

778786
"store" => {
779-
let val = from_immediate(bcx, llargs[1]);
780-
let ptr = PointerCast(bcx, llargs[0], val_ty(val).ptr_to());
781-
AtomicStore(bcx, val, ptr, order);
787+
let sty = &substs.types.get(FnSpace, 0).sty;
788+
if int_type_width_signed(sty, ccx).is_some() {
789+
AtomicStore(bcx, llargs[1], llargs[0], order);
790+
} else {
791+
span_invalid_monomorphization_error(
792+
tcx.sess, span,
793+
&format!("invalid monomorphization of `{}` intrinsic: \
794+
expected basic integer type, found `{}`", name, sty));
795+
}
782796
C_nil(ccx)
783797
}
784798

@@ -809,9 +823,16 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
809823
_ => ccx.sess().fatal("unknown atomic operation")
810824
};
811825

812-
let val = from_immediate(bcx, llargs[1]);
813-
let ptr = PointerCast(bcx, llargs[0], val_ty(val).ptr_to());
814-
AtomicRMW(bcx, atom_op, ptr, val, order)
826+
let sty = &substs.types.get(FnSpace, 0).sty;
827+
if int_type_width_signed(sty, ccx).is_some() {
828+
AtomicRMW(bcx, atom_op, llargs[0], llargs[1], order)
829+
} else {
830+
span_invalid_monomorphization_error(
831+
tcx.sess, span,
832+
&format!("invalid monomorphization of `{}` intrinsic: \
833+
expected basic integer type, found `{}`", name, sty));
834+
C_nil(ccx)
835+
}
815836
}
816837
}
817838

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(core_intrinsics, rustc_attrs)]
12+
#![allow(warnings)]
13+
14+
use std::intrinsics;
15+
16+
#[derive(Copy, Clone)]
17+
struct Foo(i64);
18+
type Bar = &'static Fn();
19+
type Quux = [u8; 100];
20+
21+
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
22+
unsafe fn test_bool_load(p: &mut bool, v: bool) {
23+
intrinsics::atomic_load(p);
24+
//~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `bool`
25+
}
26+
27+
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
28+
unsafe fn test_bool_store(p: &mut bool, v: bool) {
29+
intrinsics::atomic_store(p, v);
30+
//~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `bool`
31+
}
32+
33+
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
34+
unsafe fn test_bool_xchg(p: &mut bool, v: bool) {
35+
intrinsics::atomic_xchg(p, v);
36+
//~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `bool`
37+
}
38+
39+
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
40+
unsafe fn test_bool_cxchg(p: &mut bool, v: bool) {
41+
intrinsics::atomic_cxchg(p, v, v);
42+
//~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
43+
}
44+
45+
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
46+
unsafe fn test_Foo_load(p: &mut Foo, v: Foo) {
47+
intrinsics::atomic_load(p);
48+
//~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `Foo`
49+
}
50+
51+
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
52+
unsafe fn test_Foo_store(p: &mut Foo, v: Foo) {
53+
intrinsics::atomic_store(p, v);
54+
//~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `Foo`
55+
}
56+
57+
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
58+
unsafe fn test_Foo_xchg(p: &mut Foo, v: Foo) {
59+
intrinsics::atomic_xchg(p, v);
60+
//~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
61+
}
62+
63+
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
64+
unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) {
65+
intrinsics::atomic_cxchg(p, v, v);
66+
//~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
67+
}
68+
69+
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
70+
unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
71+
intrinsics::atomic_load(p);
72+
//~^ ERROR expected basic integer type, found `&'static std::ops::Fn() + 'static`
73+
}
74+
75+
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
76+
unsafe fn test_Bar_store(p: &mut Bar, v: Bar) {
77+
intrinsics::atomic_store(p, v);
78+
//~^ ERROR expected basic integer type, found `&'static std::ops::Fn() + 'static`
79+
}
80+
81+
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
82+
unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) {
83+
intrinsics::atomic_xchg(p, v);
84+
//~^ ERROR expected basic integer type, found `&'static std::ops::Fn() + 'static`
85+
}
86+
87+
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
88+
unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
89+
intrinsics::atomic_cxchg(p, v, v);
90+
//~^ ERROR expected basic integer type, found `&'static std::ops::Fn() + 'static`
91+
}
92+
93+
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
94+
unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
95+
intrinsics::atomic_load(p);
96+
//~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
97+
}
98+
99+
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
100+
unsafe fn test_Quux_store(p: &mut Quux, v: Quux) {
101+
intrinsics::atomic_store(p, v);
102+
//~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
103+
}
104+
105+
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
106+
unsafe fn test_Quux_xchg(p: &mut Quux, v: Quux) {
107+
intrinsics::atomic_xchg(p, v);
108+
//~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
109+
}
110+
111+
#[rustc_no_mir] // FIXME #27840 MIR doesn't provide precise spans for calls.
112+
unsafe fn test_Quux_cxchg(p: &mut Quux, v: Quux) {
113+
intrinsics::atomic_cxchg(p, v, v);
114+
//~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
115+
}
116+
117+
fn main() {}

‎src/test/run-pass/issue-23550.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,16 @@ use std::intrinsics;
1616
#[derive(Copy, Clone)]
1717
struct Wrap(i64);
1818

19-
// These volatile and atomic intrinsics used to cause an ICE
19+
// These volatile intrinsics used to cause an ICE
2020

2121
unsafe fn test_bool(p: &mut bool, v: bool) {
2222
intrinsics::volatile_load(p);
2323
intrinsics::volatile_store(p, v);
24-
intrinsics::atomic_load(p);
25-
intrinsics::atomic_cxchg(p, v, v);
26-
intrinsics::atomic_store(p, v);
27-
intrinsics::atomic_xchg(p, v);
2824
}
2925

3026
unsafe fn test_immediate_fca(p: &mut Wrap, v: Wrap) {
3127
intrinsics::volatile_load(p);
3228
intrinsics::volatile_store(p, v);
33-
intrinsics::atomic_load(p);
34-
intrinsics::atomic_cxchg(p, v, v);
35-
intrinsics::atomic_store(p, v);
36-
intrinsics::atomic_xchg(p, v);
3729
}
3830

3931
fn main() {}

0 commit comments

Comments
 (0)