Skip to content

Commit a1a4a0a

Browse files
committed
---
yaml --- r: 282012 b: refs/heads/stable c: 77f3484 h: refs/heads/master
1 parent bc80490 commit a1a4a0a

File tree

15 files changed

+241
-389
lines changed

15 files changed

+241
-389
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ refs/heads/tmp: e06d2ad9fcd5027bcaac5b08fc9aa39a49d0ecd3
2929
refs/tags/1.0.0-alpha.2: 4c705f6bc559886632d3871b04f58aab093bfa2f
3030
refs/tags/homu-tmp: 3c795e08d6f4a532f12f3f8e1837db5e0647f8b0
3131
refs/tags/1.0.0-beta: 8cbb92b53468ee2b0c2d3eeb8567005953d40828
32-
refs/heads/stable: de5f8244f20e434d2e0d351c7f4b55e604b4f3b3
32+
refs/heads/stable: 77f34841489767804ffe3d0f20d5469ecc5cf417
3333
refs/tags/1.0.0: 55bd4f8ff2b323f317ae89e254ce87162d52a375
3434
refs/tags/1.1.0: bc3c16f09287e5545c1d3f76b7abd54f2eca868b
3535
refs/tags/1.2.0: f557861f822c34f07270347b94b5280de20a597e

branches/stable/src/librustc_llvm/lib.rs

Lines changed: 6 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -212,21 +212,21 @@ impl Attributes {
212212
self
213213
}
214214

215-
pub fn apply_llfn(&self, idx: c_uint, llfn: ValueRef) {
215+
pub fn apply_llfn(&self, idx: usize, llfn: ValueRef) {
216216
unsafe {
217-
LLVMAddFunctionAttribute(llfn, idx, self.regular.bits());
217+
LLVMAddFunctionAttribute(llfn, idx as c_uint, self.regular.bits());
218218
if self.dereferenceable_bytes != 0 {
219-
LLVMAddDereferenceableAttr(llfn, idx,
219+
LLVMAddDereferenceableAttr(llfn, idx as c_uint,
220220
self.dereferenceable_bytes);
221221
}
222222
}
223223
}
224224

225-
pub fn apply_callsite(&self, idx: c_uint, callsite: ValueRef) {
225+
pub fn apply_callsite(&self, idx: usize, callsite: ValueRef) {
226226
unsafe {
227-
LLVMAddCallSiteAttribute(callsite, idx, self.regular.bits());
227+
LLVMAddCallSiteAttribute(callsite, idx as c_uint, self.regular.bits());
228228
if self.dereferenceable_bytes != 0 {
229-
LLVMAddDereferenceableCallSiteAttr(callsite, idx,
229+
LLVMAddDereferenceableCallSiteAttr(callsite, idx as c_uint,
230230
self.dereferenceable_bytes);
231231
}
232232
}
@@ -240,49 +240,6 @@ pub enum AttributeSet {
240240
FunctionIndex = !0
241241
}
242242

243-
pub struct AttrBuilder {
244-
attrs: Vec<(usize, Attributes)>
245-
}
246-
247-
impl AttrBuilder {
248-
pub fn new() -> AttrBuilder {
249-
AttrBuilder {
250-
attrs: Vec::new()
251-
}
252-
}
253-
254-
pub fn arg(&mut self, idx: usize) -> &mut Attributes {
255-
let mut found = None;
256-
for (i, &(idx2, _)) in self.attrs.iter().enumerate() {
257-
if idx == idx2 {
258-
found = Some(i);
259-
break;
260-
}
261-
}
262-
let i = found.unwrap_or_else(|| {
263-
self.attrs.push((idx, Attributes::default()));
264-
self.attrs.len() - 1
265-
});
266-
&mut self.attrs[i].1
267-
}
268-
269-
pub fn ret(&mut self) -> &mut Attributes {
270-
self.arg(ReturnIndex as usize)
271-
}
272-
273-
pub fn apply_llfn(&self, llfn: ValueRef) {
274-
for &(idx, ref attr) in &self.attrs {
275-
attr.apply_llfn(idx as c_uint, llfn);
276-
}
277-
}
278-
279-
pub fn apply_callsite(&self, callsite: ValueRef) {
280-
for &(idx, ref attr) in &self.attrs {
281-
attr.apply_callsite(idx as c_uint, callsite);
282-
}
283-
}
284-
}
285-
286243
// enum for the LLVM IntPredicate type
287244
#[derive(Copy, Clone)]
288245
pub enum IntPredicate {

branches/stable/src/librustc_trans/trans/abi.rs

Lines changed: 104 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use llvm;
11+
use llvm::{self, ValueRef};
1212
use trans::common::{return_type_is_void, type_is_fat_ptr};
1313
use trans::context::CrateContext;
1414
use trans::cabi_x86;
@@ -24,6 +24,7 @@ use trans::machine::{llsize_of_alloc, llsize_of_real};
2424
use trans::type_::Type;
2525
use trans::type_of;
2626

27+
use rustc_front::hir;
2728
use middle::ty::{self, Ty};
2829

2930
pub use syntax::abi::Abi;
@@ -204,22 +205,102 @@ impl FnType {
204205
}
205206
};
206207

207-
let ret = match sig.output {
208+
let mut ret = match sig.output {
208209
ty::FnConverging(ret_ty) if !return_type_is_void(ccx, ret_ty) => {
209210
arg_of(ret_ty)
210211
}
211212
_ => ArgType::new(Type::void(ccx), Type::void(ccx))
212213
};
213214

215+
if let ty::FnConverging(ret_ty) = sig.output {
216+
if !type_is_fat_ptr(ccx.tcx(), ret_ty) {
217+
// The `noalias` attribute on the return value is useful to a
218+
// function ptr caller.
219+
if let ty::TyBox(_) = ret_ty.sty {
220+
// `Box` pointer return values never alias because ownership
221+
// is transferred
222+
ret.attrs.set(llvm::Attribute::NoAlias);
223+
}
224+
225+
// We can also mark the return value as `dereferenceable` in certain cases
226+
match ret_ty.sty {
227+
// These are not really pointers but pairs, (pointer, len)
228+
ty::TyRef(_, ty::TypeAndMut { ty, .. }) |
229+
ty::TyBox(ty) => {
230+
let llty = type_of::sizing_type_of(ccx, ty);
231+
let llsz = llsize_of_real(ccx, llty);
232+
ret.attrs.set_dereferenceable(llsz);
233+
}
234+
_ => {}
235+
}
236+
}
237+
}
238+
214239
let mut args = Vec::with_capacity(inputs.len() + extra_args.len());
240+
241+
// Handle safe Rust thin and fat pointers.
242+
let rust_ptr_attrs = |ty: Ty<'tcx>, arg: &mut ArgType| match ty.sty {
243+
// `Box` pointer parameters never alias because ownership is transferred
244+
ty::TyBox(inner) => {
245+
arg.attrs.set(llvm::Attribute::NoAlias);
246+
Some(inner)
247+
}
248+
249+
ty::TyRef(b, mt) => {
250+
use middle::ty::{BrAnon, ReLateBound};
251+
252+
// `&mut` pointer parameters never alias other parameters, or mutable global data
253+
//
254+
// `&T` where `T` contains no `UnsafeCell<U>` is immutable, and can be marked as
255+
// both `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely
256+
// on memory dependencies rather than pointer equality
257+
let interior_unsafe = mt.ty.type_contents(ccx.tcx()).interior_unsafe();
258+
259+
if mt.mutbl != hir::MutMutable && !interior_unsafe {
260+
arg.attrs.set(llvm::Attribute::NoAlias);
261+
}
262+
263+
if mt.mutbl == hir::MutImmutable && !interior_unsafe {
264+
arg.attrs.set(llvm::Attribute::ReadOnly);
265+
}
266+
267+
// When a reference in an argument has no named lifetime, it's
268+
// impossible for that reference to escape this function
269+
// (returned or stored beyond the call by a closure).
270+
if let ReLateBound(_, BrAnon(_)) = *b {
271+
arg.attrs.set(llvm::Attribute::NoCapture);
272+
}
273+
274+
Some(mt.ty)
275+
}
276+
_ => None
277+
};
278+
215279
for ty in inputs.iter().chain(extra_args.iter()) {
216-
let arg = arg_of(ty);
280+
let mut arg = arg_of(ty);
281+
217282
if type_is_fat_ptr(ccx.tcx(), ty) {
218-
let original = arg.original_ty.field_types();
219-
let sizing = arg.ty.field_types();
220-
args.extend(original.into_iter().zip(sizing)
221-
.map(|(o, s)| ArgType::new(o, s)));
283+
let original_tys = arg.original_ty.field_types();
284+
let sizing_tys = arg.ty.field_types();
285+
assert_eq!((original_tys.len(), sizing_tys.len()), (2, 2));
286+
287+
let mut data = ArgType::new(original_tys[0], sizing_tys[0]);
288+
let mut info = ArgType::new(original_tys[1], sizing_tys[1]);
289+
290+
if let Some(inner) = rust_ptr_attrs(ty, &mut data) {
291+
data.attrs.set(llvm::Attribute::NonNull);
292+
if ccx.tcx().struct_tail(inner).is_trait() {
293+
info.attrs.set(llvm::Attribute::NonNull);
294+
}
295+
}
296+
args.push(data);
297+
args.push(info);
222298
} else {
299+
if let Some(inner) = rust_ptr_attrs(ty, &mut arg) {
300+
let llty = type_of::sizing_type_of(ccx, inner);
301+
let llsz = llsize_of_real(ccx, llty);
302+
arg.attrs.set_dereferenceable(llsz);
303+
}
223304
args.push(arg);
224305
}
225306
}
@@ -327,18 +408,29 @@ impl FnType {
327408
}
328409
}
329410

330-
pub fn llvm_attrs(&self) -> llvm::AttrBuilder {
331-
let mut attrs = llvm::AttrBuilder::new();
411+
pub fn apply_attrs_llfn(&self, llfn: ValueRef) {
412+
let mut i = if self.ret.is_indirect() { 1 } else { 0 };
413+
self.ret.attrs.apply_llfn(i, llfn);
414+
i += 1;
415+
for arg in &self.args {
416+
if !arg.is_ignore() {
417+
if arg.pad.is_some() { i += 1; }
418+
arg.attrs.apply_llfn(i, llfn);
419+
i += 1;
420+
}
421+
}
422+
}
423+
424+
pub fn apply_attrs_callsite(&self, callsite: ValueRef) {
332425
let mut i = if self.ret.is_indirect() { 1 } else { 0 };
333-
*attrs.arg(i) = self.ret.attrs;
426+
self.ret.attrs.apply_callsite(i, callsite);
334427
i += 1;
335428
for arg in &self.args {
336429
if !arg.is_ignore() {
337430
if arg.pad.is_some() { i += 1; }
338-
*attrs.arg(i) = arg.attrs;
431+
arg.attrs.apply_callsite(i, callsite);
339432
i += 1;
340433
}
341434
}
342-
attrs
343435
}
344436
}

0 commit comments

Comments
 (0)