diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index a80ae9e2596da..6d1b1e55cba8d 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -314,6 +314,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option void); ifn!("llvm.memset.p0i8.i64" fn(i8p, t_i8, t_i64, t_i32, i1) -> void); + ifn!("llvm.prefetch" fn(i8p, t_i32, t_i32, t_i32) -> void); ifn!("llvm.trap" fn() -> void); ifn!("llvm.debugtrap" fn() -> void); ifn!("llvm.frameaddress" fn(t_i32) -> i8p); diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index 0719288bb0285..ec5678904d42c 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -188,6 +188,15 @@ pub fn trans_intrinsic(ccx: &CrateContext, Ret(bcx, llcall); } + fn prefetch_intrinsic(bcx: &Block, rw: i32, locality: i32, cache: i32) { + let ccx = bcx.ccx(); + let ptr = get_param(bcx.fcx.llfn, bcx.fcx.arg_pos(0u)); + let ptri8 = PointerCast(bcx, ptr, Type::i8p(bcx.ccx())); + let llfn = bcx.ccx().get_intrinsic(&("llvm.prefetch")); + Call(bcx, llfn, [ptri8, C_i32(ccx, rw), C_i32(ccx, locality), C_i32(ccx, cache)], []); + RetVoid(bcx) + } + let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx(), item.id)); let arena = TypedArena::new(); @@ -283,6 +292,44 @@ pub fn trans_intrinsic(ccx: &CrateContext, return; } + if name.get().starts_with("prefetch") { + let mut rw = None; + let rw_default = 0; // read + let mut locality = None; + let locality_default = 3; // extreme + let mut cache = None; + let cache_default = 1; // data cache + + let setparam = |param: &mut Option, val: i32| { + match *param { + None => { + *param = Some(val); + } + _ => ccx.sess().span_fatal(item.span, "conflicting arguments in prefetch operation name") + } + }; + + for part in name.get().split('_').skip(1) { + match part { + "read" => setparam(&mut rw, 0), + "write" => setparam(&mut rw, 1), + "extreme" => setparam(&mut locality, 3), + "high" => setparam(&mut locality, 2), + "low" => setparam(&mut locality, 1), + "none" => setparam(&mut locality, 0), + "dcache" => setparam(&mut cache, 1), + "icache" => setparam(&mut cache, 0), + _ => ccx.sess().span_fatal(item.span, "unknown part in prefetch operation name") + } + } + prefetch_intrinsic(bcx, + rw.unwrap_or(rw_default), + locality.unwrap_or(locality_default), + cache.unwrap_or(cache_default)); + fcx.cleanup(); + return; + } + match name.get() { "abort" => { let llfn = bcx.ccx().get_intrinsic(&("llvm.trap")); diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index be19c2ef19953..6e1f81e9620e9 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -4392,6 +4392,11 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { } } + } else if name.get().starts_with("prefetch") { + match name.get().find_str("write") { + None => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))), ty::mk_nil()), + _ => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0))), ty::mk_nil()) + } } else { match name.get() { "abort" => (0, Vec::new(), ty::mk_bot()), diff --git a/src/test/run-pass/intrinsic-prefetch.rs b/src/test/run-pass/intrinsic-prefetch.rs new file mode 100644 index 0000000000000..3e2be202b770f --- /dev/null +++ b/src/test/run-pass/intrinsic-prefetch.rs @@ -0,0 +1,30 @@ +// 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. + +mod rusti { + extern "rust-intrinsic" { + pub fn prefetch(address: *T); + pub fn prefetch_write(address: *mut T); + } +} + +fn main() { + let i = 1; + let j = box 1; + unsafe { + let ip: *int = &i; + let jp: *mut int = std::mem::transmute(j); + + rusti::prefetch(ip); + rusti::prefetch_write(jp); + + drop(std::mem::transmute::<_, Box>(jp)); + } +}