diff --git a/src/bootstrap/build/native.rs b/src/bootstrap/build/native.rs index 5691b2da6a448..187b8c6b4ddd5 100644 --- a/src/bootstrap/build/native.rs +++ b/src/bootstrap/build/native.rs @@ -63,7 +63,7 @@ pub fn llvm(build: &Build, target: &str) { .out_dir(&dst) .profile(if build.config.llvm_optimize {"Release"} else {"Debug"}) .define("LLVM_ENABLE_ASSERTIONS", assertions) - .define("LLVM_TARGETS_TO_BUILD", "X86;ARM;AArch64;Mips;PowerPC") + .define("LLVM_TARGETS_TO_BUILD", "X86;ARM;AArch64;Mips;PowerPC;NVPTX") .define("LLVM_INCLUDE_EXAMPLES", "OFF") .define("LLVM_INCLUDE_TESTS", "OFF") .define("LLVM_INCLUDE_DOCS", "OFF") diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 94baf188bcaee..5155e619bf07d 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -602,4 +602,23 @@ extern "rust-intrinsic" { /// on MSVC it's `*mut [usize; 2]`. For more information see the compiler's /// source as well as std's catch implementation. pub fn try(f: fn(*mut u8), data: *mut u8, local_ptr: *mut u8) -> i32; + +} + +#[cfg(not(stage0))] +#[cfg(arch = "nvptx")] +extern "rust-intrinsic" { + pub fn thread_idx_x() -> i32; + pub fn thread_idx_y() -> i32; + pub fn thread_idx_z() -> i32; + pub fn block_idx_x() -> i32; + pub fn block_idx_y() -> i32; + pub fn block_idx_z() -> i32; + pub fn block_dim_x() -> i32; + pub fn block_dim_y() -> i32; + pub fn block_dim_z() -> i32; + pub fn grid_dim_x() -> i32; + pub fn grid_dim_y() -> i32; + pub fn grid_dim_z() -> i32; + pub fn syncthreads(); } diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 2163a8a1689b6..7c9fd9d7e4d26 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -141,7 +141,9 @@ supported_targets! { ("i586-pc-windows-msvc", i586_pc_windows_msvc), ("le32-unknown-nacl", le32_unknown_nacl), - ("asmjs-unknown-emscripten", asmjs_unknown_emscripten) + ("asmjs-unknown-emscripten", asmjs_unknown_emscripten), + ("nvptx-unknown-unknown", nvptx_unknown_unknown), + ("nvptx64-unknown-unknown", nvptx64_unknown_unknown) } /// Everything `rustc` knows about how to compile for a specific target. diff --git a/src/librustc_back/target/nvptx64_unknown_unknown.rs b/src/librustc_back/target/nvptx64_unknown_unknown.rs new file mode 100644 index 0000000000000..d5e6747a61e2d --- /dev/null +++ b/src/librustc_back/target/nvptx64_unknown_unknown.rs @@ -0,0 +1,36 @@ +// 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. + +use super::{Target, TargetOptions}; + +pub fn target() -> Target { + let opts = TargetOptions { + linker: "".to_string(), + ar: "".to_string(), + + cpu: "sm_20".to_string(), + dynamic_linking: false, + executables: false, + no_compiler_rt: true, + allow_asm: false, + .. Default::default() + }; + Target { + llvm_target: "nvptx64-unknown-unknown".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_os: "none".to_string(), + target_env: "".to_string(), + target_vendor: "unknown".to_string(), + data_layout: "e-i64:64-v16:16-v32:32-n16:32:64".to_string(), + arch: "nvptx".to_string(), + options: opts, + } +} diff --git a/src/librustc_back/target/nvptx_unknown_unknown.rs b/src/librustc_back/target/nvptx_unknown_unknown.rs new file mode 100644 index 0000000000000..dc5005a6bc627 --- /dev/null +++ b/src/librustc_back/target/nvptx_unknown_unknown.rs @@ -0,0 +1,36 @@ +// 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. + +use super::{Target, TargetOptions}; + +pub fn target() -> Target { + let opts = TargetOptions { + linker: "".to_string(), + ar: "".to_string(), + + cpu: "sm_20".to_string(), + dynamic_linking: false, + executables: false, + no_compiler_rt: true, + allow_asm: false, + .. Default::default() + }; + Target { + llvm_target: "nvptx-unknown-unknown".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_os: "none".to_string(), + target_env: "".to_string(), + target_vendor: "unknown".to_string(), + data_layout: "e-p:32:32-i64:64-v16:16-v32:32-n16:32:64".to_string(), + arch: "nvptx".to_string(), + options: opts, + } +} diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 250aafd77a826..a2917116bef99 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -68,7 +68,7 @@ fn main() { let host = env::var("HOST").unwrap(); let is_crossed = target != host; - let optional_components = ["x86", "arm", "aarch64", "mips", "powerpc", "pnacl"]; + let optional_components = ["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", "nvptx"]; // FIXME: surely we don't need all these components, right? Stuff like mcjit // or interpreter the compiler itself never uses. diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index e757201c88633..36be86f3794ec 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -2407,6 +2407,11 @@ pub fn initialize_available_targets() { LLVMInitializeMipsTargetMC, LLVMInitializeMipsAsmPrinter, LLVMInitializeMipsAsmParser); + init_target!(llvm_component = "nvptx", + LLVMInitializeNVPTXTargetInfo, + LLVMInitializeNVPTXTarget, + LLVMInitializeNVPTXTargetMC, + LLVMInitializeNVPTXAsmPrinter); init_target!(llvm_component = "powerpc", LLVMInitializePowerPCTargetInfo, LLVMInitializePowerPCTarget, diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index bfcb1ae33b301..f65361bf2da93 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -1097,6 +1097,19 @@ fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option { ifn!("llvm.localrecover", fn(i8p, i8p, t_i32) -> i8p); ifn!("llvm.x86.seh.recoverfp", fn(i8p, i8p) -> i8p); + ifn!("llvm.cuda.syncthreads", fn() -> void); + ifn!("llvm.nvvm.read.ptx.sreg.tid.x", fn() -> t_i32); + ifn!("llvm.nvvm.read.ptx.sreg.tid.y", fn() -> t_i32); + ifn!("llvm.nvvm.read.ptx.sreg.tid.z", fn() -> t_i32); + ifn!("llvm.nvvm.read.ptx.sreg.ctaid.x", fn() -> t_i32); + ifn!("llvm.nvvm.read.ptx.sreg.ctaid.y", fn() -> t_i32); + ifn!("llvm.nvvm.read.ptx.sreg.ctaid.z", fn() -> t_i32); + ifn!("llvm.nvvm.read.ptx.sreg.ntid.x", fn() -> t_i32); + ifn!("llvm.nvvm.read.ptx.sreg.ntid.y", fn() -> t_i32); + ifn!("llvm.nvvm.read.ptx.sreg.ntid.z", fn() -> t_i32); + ifn!("llvm.nvvm.read.ptx.sreg.nctaid.x", fn() -> t_i32); + ifn!("llvm.nvvm.read.ptx.sreg.nctaid.y", fn() -> t_i32); + ifn!("llvm.nvvm.read.ptx.sreg.nctaid.z", fn() -> t_i32); ifn!("llvm.assume", fn(i1) -> void); if ccx.sess().opts.debuginfo != NoDebugInfo { diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 54c825fa5face..5d2e1870c55fe 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -89,6 +89,19 @@ fn get_simple_intrinsic(ccx: &CrateContext, name: &str) -> Option { "roundf32" => "llvm.round.f32", "roundf64" => "llvm.round.f64", "assume" => "llvm.assume", + "thread_idx_x" => "llvm.nvvm.read.ptx.sreg.tid.x", + "thread_idx_y" => "llvm.nvvm.read.ptx.sreg.tid.y", + "thread_idx_z" => "llvm.nvvm.read.ptx.sreg.tid.z", + "block_idx_x" => "llvm.nvvm.read.ptx.sreg.ctaid.x", + "block_idx_y" => "llvm.nvvm.read.ptx.sreg.ctaid.y", + "block_idx_z" => "llvm.nvvm.read.ptx.sreg.ctaid.z", + "block_dim_x" => "llvm.nvvm.read.ptx.sreg.ntid.x", + "block_dim_y" => "llvm.nvvm.read.ptx.sreg.ntid.y", + "block_dim_z" => "llvm.nvvm.read.ptx.sreg.ntid.z", + "grid_dim_x" => "llvm.nvvm.read.ptx.sreg.nctaid.x", + "grid_dim_y" => "llvm.nvvm.read.ptx.sreg.nctaid.y", + "grid_dim_z" => "llvm.nvvm.read.ptx.sreg.nctaid.z", + "syncthreads" => "llvm.cuda.syncthreads", _ => return None }; Some(ccx.get_intrinsic(&llvm_name)) diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index f120e38630b8a..d84abd1a87f2b 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -298,6 +298,15 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { (0, vec![tcx.mk_fn_ptr(fn_ty), mut_u8, mut_u8], tcx.types.i32) } + "thread_idx_x" | "thread_idx_y" | "thread_idx_z" | + "block_idx_x" | "block_idx_y" | "block_idx_z" | + "block_dim_x" | "block_dim_y" | "block_dim_z" | + "grid_dim_x" | "grid_dim_y" | "grid_dim_z" => { + (0, vec![], tcx.types.i32) + } + + "syncthreads" => (0, vec![], tcx.mk_nil()), + ref other => { span_err!(tcx.sess, it.span, E0093, "unrecognized intrinsic function: `{}`", *other);