From c558a2ae37052dc1f12aa4e40578eb4ae9aca3b9 Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Sun, 9 Apr 2017 02:03:31 -0400 Subject: [PATCH 1/4] Add Hexagon support This requires an updated LLVM with D31999 and D32000 to build libcore. A basic hello world builds and runs successfully on the hexagon simulator. --- src/librustc_llvm/build.rs | 2 +- src/librustc_llvm/lib.rs | 6 +++++ src/librustc_trans/abi.rs | 2 ++ src/librustc_trans/cabi_hexagon.rs | 43 ++++++++++++++++++++++++++++++ src/librustc_trans/lib.rs | 1 + src/rustllvm/PassWrapper.cpp | 9 ++++++- 6 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 src/librustc_trans/cabi_hexagon.rs diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 4871f60466dfd..3c88ae886d6f5 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -94,7 +94,7 @@ fn main() { let optional_components = ["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", "systemz", "jsbackend", "msp430", - "sparc", "nvptx"]; + "sparc", "nvptx", "hexagon"]; // 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 7c52ceae459cd..c9b3a7ff3f3aa 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -382,6 +382,12 @@ pub fn initialize_available_targets() { LLVMInitializeNVPTXTarget, LLVMInitializeNVPTXTargetMC, LLVMInitializeNVPTXAsmPrinter); + init_target!(llvm_component = "hexagon", + LLVMInitializeHexagonTargetInfo, + LLVMInitializeHexagonTarget, + LLVMInitializeHexagonTargetMC, + LLVMInitializeHexagonAsmPrinter, + LLVMInitializeHexagonAsmParser); } pub fn last_error() -> Option { diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 998e392b1f907..a6b0eb473eb8e 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -29,6 +29,7 @@ use cabi_sparc; use cabi_sparc64; use cabi_nvptx; use cabi_nvptx64; +use cabi_hexagon; use machine::llalign_of_min; use type_::Type; use type_of; @@ -896,6 +897,7 @@ impl<'a, 'tcx> FnType<'tcx> { "sparc64" => cabi_sparc64::compute_abi_info(ccx, self), "nvptx" => cabi_nvptx::compute_abi_info(ccx, self), "nvptx64" => cabi_nvptx64::compute_abi_info(ccx, self), + "hexagon" => cabi_hexagon::compute_abi_info(ccx, self), a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a)) } diff --git a/src/librustc_trans/cabi_hexagon.rs b/src/librustc_trans/cabi_hexagon.rs new file mode 100644 index 0000000000000..1acda72675c31 --- /dev/null +++ b/src/librustc_trans/cabi_hexagon.rs @@ -0,0 +1,43 @@ +// Copyright 2012-2013 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. + +#![allow(non_upper_case_globals)] + +use abi::{FnType, ArgType, LayoutExt}; +use context::CrateContext; + +fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tcx>) { + if ret.layout.is_aggregate() && ret.layout.size(ccx).bits() > 64 { + ret.make_indirect(ccx); + } else { + ret.extend_integer_width_to(32); + } +} + +fn classify_arg_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &mut ArgType<'tcx>) { + if arg.layout.is_aggregate() && arg.layout.size(ccx).bits() > 64 { + arg.make_indirect(ccx); + } else { + arg.extend_integer_width_to(32); + } +} + +pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType<'tcx>) { + if !fty.ret.is_ignore() { + classify_ret_ty(ccx, &mut fty.ret); + } + + for arg in &mut fty.args { + if arg.is_ignore() { + continue; + } + classify_arg_ty(ccx, arg); + } +} diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 117d8568500b8..d5fc2ee5e25e0 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -97,6 +97,7 @@ mod builder; mod cabi_aarch64; mod cabi_arm; mod cabi_asmjs; +mod cabi_hexagon; mod cabi_mips; mod cabi_mips64; mod cabi_msp430; diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index c410a6b1349d6..b938f94cda2cb 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -147,6 +147,12 @@ extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) { #define SUBTARGET_SPARC #endif +#ifdef LLVM_COMPONENT_HEXAGON +#define SUBTARGET_HEXAGON SUBTARGET(Hexagon) +#else +#define SUBTARGET_HEXAGON +#endif + #define GEN_SUBTARGETS \ SUBTARGET_X86 \ SUBTARGET_ARM \ @@ -155,7 +161,8 @@ extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) { SUBTARGET_PPC \ SUBTARGET_SYSTEMZ \ SUBTARGET_MSP430 \ - SUBTARGET_SPARC + SUBTARGET_SPARC \ + SUBTARGET_HEXAGON #define SUBTARGET(x) \ namespace llvm { \ From 32aeb22f5488acc51b01d93684d35d097e6e23f5 Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Tue, 25 Apr 2017 18:08:13 -0400 Subject: [PATCH 2/4] Avoid the hexagon backend on old versions of LLVM --- src/librustc_llvm/build.rs | 66 ++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 3c88ae886d6f5..3fd75146193e7 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -17,30 +17,24 @@ use std::path::{PathBuf, Path}; use build_helper::output; -fn detect_llvm_link(llvm_config: &Path) -> (&'static str, Option<&'static str>) { - let mut version_cmd = Command::new(llvm_config); - version_cmd.arg("--version"); - let version_output = output(&mut version_cmd); - let mut parts = version_output.split('.').take(2) - .filter_map(|s| s.parse::().ok()); - if let (Some(major), Some(minor)) = (parts.next(), parts.next()) { - if major > 3 || (major == 3 && minor >= 9) { - // Force the link mode we want, preferring static by default, but - // possibly overridden by `configure --enable-llvm-link-shared`. - if env::var_os("LLVM_LINK_SHARED").is_some() { - return ("dylib", Some("--link-shared")); - } else { - return ("static", Some("--link-static")); - } - } else if major == 3 && minor == 8 { - // Find out LLVM's default linking mode. - let mut mode_cmd = Command::new(llvm_config); - mode_cmd.arg("--shared-mode"); - if output(&mut mode_cmd).trim() == "shared" { - return ("dylib", None); - } else { - return ("static", None); - } +fn detect_llvm_link(major: u32, minor: u32, llvm_config: &Path) + -> (&'static str, Option<&'static str>) { + if major > 3 || (major == 3 && minor >= 9) { + // Force the link mode we want, preferring static by default, but + // possibly overridden by `configure --enable-llvm-link-shared`. + if env::var_os("LLVM_LINK_SHARED").is_some() { + return ("dylib", Some("--link-shared")); + } else { + return ("static", Some("--link-static")); + } + } else if major == 3 && minor == 8 { + // Find out LLVM's default linking mode. + let mut mode_cmd = Command::new(llvm_config); + mode_cmd.arg("--shared-mode"); + if output(&mut mode_cmd).trim() == "shared" { + return ("dylib", None); + } else { + return ("static", None); } } ("static", None) @@ -92,9 +86,25 @@ fn main() { let host = env::var("HOST").expect("HOST was not set"); let is_crossed = target != host; - let optional_components = - ["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", "systemz", "jsbackend", "msp430", - "sparc", "nvptx", "hexagon"]; + let mut optional_components = + vec!["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", + "systemz", "jsbackend", "msp430", "sparc", "nvptx"]; + + let mut version_cmd = Command::new(&llvm_config); + version_cmd.arg("--version"); + let version_output = output(&mut version_cmd); + let mut parts = version_output.split('.').take(2) + .filter_map(|s| s.parse::().ok()); + let (major, minor) = + if let (Some(major), Some(minor)) = (parts.next(), parts.next()) { + (major, minor) + } else { + (3, 7) + }; + + if major > 3 { + optional_components.push("hexagon"); + } // FIXME: surely we don't need all these components, right? Stuff like mcjit // or interpreter the compiler itself never uses. @@ -158,7 +168,7 @@ fn main() { .cpp_link_stdlib(None) // we handle this below .compile("librustllvm.a"); - let (llvm_kind, llvm_link_arg) = detect_llvm_link(&llvm_config); + let (llvm_kind, llvm_link_arg) = detect_llvm_link(major, minor, &llvm_config); // Link in all LLVM libraries, if we're uwring the "wrong" llvm-config then // we don't pick up system libs because unfortunately they're for the host From 27b00ec752cfd65e70f213272d0d960c05dc9aae Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Tue, 25 Apr 2017 18:50:41 -0400 Subject: [PATCH 3/4] Cherry pick LLVM hexagon fixes --- src/llvm | 2 +- src/rustllvm/llvm-rebuild-trigger | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/llvm b/src/llvm index a884d21cc5f0b..878af191434cd 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit a884d21cc5f0b23a1693d1e872fd8998a4fdd17f +Subproject commit 878af191434cd716eeb13c2be7a2b1e21abf2749 diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index c8732e27b8252..52ebf449d6007 100644 --- a/src/rustllvm/llvm-rebuild-trigger +++ b/src/rustllvm/llvm-rebuild-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2017-03-23 +2017-04-25 From 22eb3c69b913091b8e363803dab973a2a8230736 Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Tue, 18 Apr 2017 16:23:47 -0400 Subject: [PATCH 4/4] Enable building the LLVM Hexagon target --- src/bootstrap/config.toml.example | 2 +- src/bootstrap/native.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index fad79022043e3..0309eca0e5dea 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -51,7 +51,7 @@ # support. You'll need to write a target specification at least, and most # likely, teach rustc about the C ABI of the target. Get in touch with the # Rust team and file an issue if you need assistance in porting! -#targets = "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX" +#targets = "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX;Hexagon" # Cap the number of parallel linker invocations when compiling LLVM. # This can be useful when building LLVM with debug info, which significantly diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 726e94e49a19e..af3fcd1ec3c26 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -81,7 +81,7 @@ pub fn llvm(build: &Build, target: &str) { // NOTE: remember to also update `config.toml.example` when changing the defaults! let llvm_targets = match build.config.llvm_targets { Some(ref s) => s, - None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX", + None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX;Hexagon", }; let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};