From 37c2a6642d3d4af12d66a15bbf56403e8e721a56 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Tue, 5 Mar 2019 15:20:30 +0000 Subject: [PATCH 1/8] The xtensa triples are recognized by the compiler. Need to implement the calling convention, target -> call -> abi --- src/librustc_llvm/build.rs | 2 +- src/librustc_llvm/lib.rs | 8 ++++++++ src/rustllvm/PassWrapper.cpp | 9 +++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 62a3757757b80..3cb07a90ea7bf 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -72,7 +72,7 @@ fn main() { let mut optional_components = vec!["x86", "arm", "aarch64", "amdgpu", "mips", "powerpc", "systemz", "jsbackend", "webassembly", "msp430", "sparc", "nvptx", - "hexagon"]; + "hexagon", "xtensa"]; let mut version_cmd = Command::new(&llvm_config); version_cmd.arg("--version"); diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 647d473f01572..a2ead07ab4f79 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -105,4 +105,12 @@ pub fn initialize_available_targets() { LLVMInitializeWebAssemblyTarget, LLVMInitializeWebAssemblyTargetMC, LLVMInitializeWebAssemblyAsmPrinter); + init_target!(llvm_component = "xtensa", + LLVMInitializeXtensaTargetInfo, + LLVMInitializeXtensaTarget, + LLVMInitializeXtensaTargetMC, + LLVMInitializeXtensaAsmPrinter + LLVMInitializeXtensaAsmParser); + ); + } diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 0cda3465dc093..6dba95ed35584 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -174,6 +174,14 @@ void LLVMRustAddLastExtensionPasses( #define SUBTARGET_HEXAGON #endif +#ifdef LLVM_COMPONENT_XTENSA +#define SUBTARGET_XTENSA SUBTARGET(XTENSA) +#else +#define SUBTARGET_XTENSA +#endif + + + #define GEN_SUBTARGETS \ SUBTARGET_X86 \ SUBTARGET_ARM \ @@ -185,6 +193,7 @@ void LLVMRustAddLastExtensionPasses( SUBTARGET_SPARC \ SUBTARGET_HEXAGON \ SUBTARGET_RISCV \ + SUBTARGET_XTENSA \ #define SUBTARGET(x) \ namespace llvm { \ From 9eca2e2e4a2cde8b43b2667dca9a70ec2e97fdb8 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Tue, 5 Mar 2019 23:36:09 +0000 Subject: [PATCH 2/8] Preliminary call abi for xtensa, it almost certainly has mistakes/ missing stuff. --- src/librustc_llvm/lib.rs | 3 +- src/librustc_target/abi/call/mod.rs | 2 + src/librustc_target/abi/call/xtensa.rs | 85 ++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 src/librustc_target/abi/call/xtensa.rs diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index a2ead07ab4f79..75e020ee45f07 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -109,8 +109,7 @@ pub fn initialize_available_targets() { LLVMInitializeXtensaTargetInfo, LLVMInitializeXtensaTarget, LLVMInitializeXtensaTargetMC, - LLVMInitializeXtensaAsmPrinter + LLVMInitializeXtensaAsmPrinter, LLVMInitializeXtensaAsmParser); - ); } diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs index fbbd120f934be..9746d76a6b7f4 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -22,6 +22,7 @@ mod x86; mod x86_64; mod x86_win64; mod wasm32; +mod xtensa; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum IgnoreMode { @@ -581,6 +582,7 @@ impl<'a, Ty> FnType<'a, Ty> { "hexagon" => hexagon::compute_abi_info(self), "riscv32" => riscv::compute_abi_info(self, 32), "riscv64" => riscv::compute_abi_info(self, 64), + "xtensa" => xtensa::compute_abi_info(self, 32), a => return Err(format!("unrecognized arch \"{}\" in target specification", a)) } diff --git a/src/librustc_target/abi/call/xtensa.rs b/src/librustc_target/abi/call/xtensa.rs new file mode 100644 index 0000000000000..d8c00005fa75a --- /dev/null +++ b/src/librustc_target/abi/call/xtensa.rs @@ -0,0 +1,85 @@ +// reference: https://github.com/espressif/clang-xtensa/commit/6fb488d2553f06029e6611cf81c6efbd45b56e47#diff-aa74ae1e1ab6b7149789237edb78e688R8450 + + +use crate::abi::call::{ArgType, FnType, Reg, Uniform}; + +const NUM_ARG_GPR: u64 = 6; +const MAX_ARG_IN_REGS_SIZE: u64 = 4 * 32; +// const MAX_ARG_DIRECT_SIZE : u64 = MAX_ARG_IN_REGS_SIZE; +const MAX_RET_IN_REGS_SIZE: u64 = 2 * 32; + +fn classify_ret_ty(arg: &mut ArgType<'_, Ty>, xlen: u64) { + // The rules for return and argument types are the same, so defer to + // classifyArgumentType. + classify_arg_ty(arg, xlen, &mut 2); // two as max return size +} + + +fn classify_arg_ty(arg: &mut ArgType<'_, Ty>, xlen: u64, remaining_gpr: &mut u64) { + // Determine the number of GPRs needed to pass the current argument + // according to the ABI. 2*XLen-aligned varargs are passed in "aligned" + // register pairs, so may consume 3 registers. + + let mut stack_required = false; + let mut required_gpr = 1u64; // at least one to start + let arg_size = arg.layout.size.bits(); + // let alignment = arg.layout.details.align.abi.bits(); + + + if arg_size > xlen && arg_size <= MAX_ARG_IN_REGS_SIZE { + required_gpr = arg_size + (xlen - 1) / xlen; + } + + if required_gpr > *remaining_gpr { + stack_required = true; + required_gpr = *remaining_gpr; } + + + *remaining_gpr -= required_gpr; + + // if a value can fit in a reg and the + // stack is not required, extend + if !arg.layout.is_aggregate() { + if arg_size < xlen && !stack_required { + arg.extend_integer_width_to(xlen); + } + return; + } + + + if arg_size as u64 <= MAX_ARG_IN_REGS_SIZE { + let align = arg.layout.align.abi.bytes(); + let total = arg.layout.size; + arg.cast_to(Uniform { + unit: if align <= 4 { Reg::i32() } else { Reg::i64() }, + total + }); + return; + } + + // if we get here the stack is required + // assert!(stack_required); + arg.make_indirect(); +} + +pub fn compute_abi_info(fty: &mut FnType<'_, Ty>, xlen: u64) { + if !fty.ret.is_ignore() { + classify_ret_ty(&mut fty.ret, xlen); + } + + let return_indirect = fty.ret.layout.size.bits() > MAX_RET_IN_REGS_SIZE || + fty.ret.is_indirect(); + + let mut remaining_gpr = if return_indirect { + NUM_ARG_GPR - 1 + } else { + NUM_ARG_GPR + }; + + for arg in &mut fty.args { + if arg.is_ignore() { + continue; + } + classify_arg_ty(arg, xlen, &mut remaining_gpr); + } +} From 4e8903bc4fdf682e96431623bc5a1abbd26ac033 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Thu, 7 Mar 2019 23:27:28 +0000 Subject: [PATCH 3/8] Tweaks to the xtensa call abi, small arrays arguments still need to be sorted, and it all needs to be verified on actual hardware --- src/librustc_target/abi/call/xtensa.rs | 72 +++++++++++++++++--------- 1 file changed, 48 insertions(+), 24 deletions(-) diff --git a/src/librustc_target/abi/call/xtensa.rs b/src/librustc_target/abi/call/xtensa.rs index d8c00005fa75a..191470bd105a3 100644 --- a/src/librustc_target/abi/call/xtensa.rs +++ b/src/librustc_target/abi/call/xtensa.rs @@ -5,7 +5,7 @@ use crate::abi::call::{ArgType, FnType, Reg, Uniform}; const NUM_ARG_GPR: u64 = 6; const MAX_ARG_IN_REGS_SIZE: u64 = 4 * 32; -// const MAX_ARG_DIRECT_SIZE : u64 = MAX_ARG_IN_REGS_SIZE; +// const MAX_ARG_DIRECT_SIZE: u64 = MAX_ARG_IN_REGS_SIZE; const MAX_RET_IN_REGS_SIZE: u64 = 2 * 32; fn classify_ret_ty(arg: &mut ArgType<'_, Ty>, xlen: u64) { @@ -21,45 +21,69 @@ fn classify_arg_ty(arg: &mut ArgType<'_, Ty>, xlen: u64, remaining_gpr: &mut // register pairs, so may consume 3 registers. let mut stack_required = false; - let mut required_gpr = 1u64; // at least one to start - let arg_size = arg.layout.size.bits(); - // let alignment = arg.layout.details.align.abi.bits(); + let arg_size = arg.layout.size; + let alignment = arg.layout.details.align.abi; - if arg_size > xlen && arg_size <= MAX_ARG_IN_REGS_SIZE { - required_gpr = arg_size + (xlen - 1) / xlen; + let mut required_gpr = 1u64; // at least one per arg + if alignment.bits() == 2 * xlen { + required_gpr = 2 + (*remaining_gpr % 2); + } else if arg_size.bits() > xlen && arg_size.bits() <= MAX_ARG_IN_REGS_SIZE { + required_gpr = arg_size.bits() + (xlen - 1) / xlen; } if required_gpr > *remaining_gpr { stack_required = true; - required_gpr = *remaining_gpr; } - - + required_gpr = *remaining_gpr; + } *remaining_gpr -= required_gpr; // if a value can fit in a reg and the // stack is not required, extend - if !arg.layout.is_aggregate() { - if arg_size < xlen && !stack_required { + if !arg.layout.is_aggregate() { // non-aggregate types + if arg_size.bits() < xlen && !stack_required { arg.extend_integer_width_to(xlen); } - return; + } else if arg_size.bits() as u64 <= MAX_ARG_IN_REGS_SIZE { // aggregate types + // Aggregates which are <= 4*32 will be passed in registers if possible, + // so coerce to integers. + + // Use a single XLen int if possible, 2*XLen if 2*XLen alignment is + // required, and a 2-element XLen array if only XLen alignment is + // required. + // if alignment == 2 * xlen { + // arg.extend_integer_width_to(xlen * 2); + // } else { + // arg.extend_integer_width_to(arg_size + (xlen - 1) / xlen); + // } + if alignment.bits() == 2 * xlen { + arg.cast_to(Uniform { + unit: Reg::i64(), + total: arg_size + }); + } else { + //TODO array type - this should be a homogenous array type + // arg.extend_integer_width_to(arg_size + (xlen - 1) / xlen); + } + + } else { + // if we get here the stack is required + assert!(stack_required); + arg.make_indirect(); } - if arg_size as u64 <= MAX_ARG_IN_REGS_SIZE { - let align = arg.layout.align.abi.bytes(); - let total = arg.layout.size; - arg.cast_to(Uniform { - unit: if align <= 4 { Reg::i32() } else { Reg::i64() }, - total - }); - return; - } + // if arg_size as u64 <= MAX_ARG_IN_REGS_SIZE { + // let align = arg.layout.align.abi.bytes(); + // let total = arg.layout.size; + // arg.cast_to(Uniform { + // unit: if align <= 4 { Reg::i32() } else { Reg::i64() }, + // total + // }); + // return; + // } - // if we get here the stack is required - // assert!(stack_required); - arg.make_indirect(); + } pub fn compute_abi_info(fty: &mut FnType<'_, Ty>, xlen: u64) { From b401dfc37d2051440bd53f29c30941bec277b8c2 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Tue, 12 Mar 2019 22:26:17 +0000 Subject: [PATCH 4/8] Add built in target, based on msp430. This uses external gcc to generate object files --- src/librustc_target/spec/mod.rs | 1 + src/librustc_target/spec/xtensa_none_elf.rs | 66 +++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/librustc_target/spec/xtensa_none_elf.rs diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 626fa374a1bd4..39a30bd756da8 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -473,6 +473,7 @@ supported_targets! { ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf), ("msp430-none-elf", msp430_none_elf), + ("xtensa-none-elf", xtensa_none_elf), ("aarch64-unknown-cloudabi", aarch64_unknown_cloudabi), ("armv7-unknown-cloudabi-eabihf", armv7_unknown_cloudabi_eabihf), diff --git a/src/librustc_target/spec/xtensa_none_elf.rs b/src/librustc_target/spec/xtensa_none_elf.rs new file mode 100644 index 0000000000000..afd043cf9047e --- /dev/null +++ b/src/librustc_target/spec/xtensa_none_elf.rs @@ -0,0 +1,66 @@ +use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult, abi::Abi}; +// use crate::spec::abi::Abi; + +pub fn target() -> TargetResult { + Ok(Target { + llvm_target: "xtensa-none-elf".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-f64:64-a:0:32-n32".to_string(), + arch: "xtensa".to_string(), + target_os: "none".to_string(), + target_env: String::new(), + target_vendor: String::new(), + linker_flavor: LinkerFlavor::Gcc, + + options: TargetOptions { + executables: true, + + // The LLVM backend currently can't generate object files. To + // workaround this LLVM generates assembly files which then we feed + // to gcc to get object files. For this reason we have a hard + // dependency on this specific gcc. + // asm_args: vec!["-mcpu=generic".to_string()], + linker: Some("xtensa-esp32-elf-gcc".to_string()), + no_integrated_as: true, + + max_atomic_width: Some(32), + atomic_cas: true, + + // Because these devices have very little resources having an + // unwinder is too onerous so we default to "abort" because the + // "unwind" strategy is very rare. + panic_strategy: PanicStrategy::Abort, + + // Similarly, one almost always never wants to use relocatable + // code because of the extra costs it involves. + relocation_model: "static".to_string(), + + // Right now we invoke an external assembler and this isn't + // compatible with multiple codegen units, and plus we probably + // don't want to invoke that many gcc instances. + default_codegen_units: Some(1), + + // Since MSP430 doesn't meaningfully support faulting on illegal + // instructions, LLVM generates a call to abort() function instead + // of a trap instruction. Such calls are 4 bytes long, and that is + // too much overhead for such small target. + trap_unreachable: false, + + // See the thumb_base.rs file for an explanation of this value + emit_debug_gdb_scripts: false, + + abi_blacklist: vec![ + Abi::Stdcall, + Abi::Fastcall, + Abi::Vectorcall, + Abi::Thiscall, + Abi::Win64, + Abi::SysV64, + ], + + .. Default::default( ) + } + }) +} From aa441cb81d7f98bbe266a88935ac89b38c91cbe7 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Mon, 27 May 2019 02:55:10 +0100 Subject: [PATCH 5/8] Add xtensa-esp32-none-elf, xtensa-esp8266-none-elf targets. Remove xtensa-none-elf --- src/librustc_target/spec/mod.rs | 3 +- .../spec/xtensa_esp32_none_elf.rs | 66 +++++++++++++++++++ .../spec/xtensa_esp8266_none_elf.rs | 66 +++++++++++++++++++ 3 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 src/librustc_target/spec/xtensa_esp32_none_elf.rs create mode 100644 src/librustc_target/spec/xtensa_esp8266_none_elf.rs diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 39a30bd756da8..54aad71acf3b5 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -473,7 +473,8 @@ supported_targets! { ("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf), ("msp430-none-elf", msp430_none_elf), - ("xtensa-none-elf", xtensa_none_elf), + ("xtensa-esp32-none-elf", xtensa_esp32_none_elf), + ("xtensa-esp8266-none-elf", xtensa_esp8266_none_elf), ("aarch64-unknown-cloudabi", aarch64_unknown_cloudabi), ("armv7-unknown-cloudabi-eabihf", armv7_unknown_cloudabi_eabihf), diff --git a/src/librustc_target/spec/xtensa_esp32_none_elf.rs b/src/librustc_target/spec/xtensa_esp32_none_elf.rs new file mode 100644 index 0000000000000..8402f1a3663fa --- /dev/null +++ b/src/librustc_target/spec/xtensa_esp32_none_elf.rs @@ -0,0 +1,66 @@ +use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult, abi::Abi}; +// use crate::spec::abi::Abi; + +pub fn target() -> TargetResult { + Ok(Target { + llvm_target: "xtensa-none-elf".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-f64:64-a:0:32-n32".to_string(), + arch: "xtensa".to_string(), + target_os: "none".to_string(), + target_env: String::new(), + target_vendor: String::new(), + linker_flavor: LinkerFlavor::Gcc, + + options: TargetOptions { + executables: true, + cpu: "esp32".to_string(), + // The LLVM backend currently can't generate object files. To + // workaround this LLVM generates assembly files which then we feed + // to gcc to get object files. For this reason we have a hard + // dependency on this specific gcc. + // asm_args: vec!["-mcpu=esp32".to_string()], + linker: Some("xtensa-esp32-elf-gcc".to_string()), + no_integrated_as: true, + + max_atomic_width: Some(32), + atomic_cas: true, + + // Because these devices have very little resources having an + // unwinder is too onerous so we default to "abort" because the + // "unwind" strategy is very rare. + panic_strategy: PanicStrategy::Abort, + + // Similarly, one almost always never wants to use relocatable + // code because of the extra costs it involves. + relocation_model: "static".to_string(), + + // Right now we invoke an external assembler and this isn't + // compatible with multiple codegen units, and plus we probably + // don't want to invoke that many gcc instances. + default_codegen_units: Some(1), + + // Since MSP430 doesn't meaningfully support faulting on illegal + // instructions, LLVM generates a call to abort() function instead + // of a trap instruction. Such calls are 4 bytes long, and that is + // too much overhead for such small target. + trap_unreachable: false, + + // See the thumb_base.rs file for an explanation of this value + emit_debug_gdb_scripts: false, + + abi_blacklist: vec![ + Abi::Stdcall, + Abi::Fastcall, + Abi::Vectorcall, + Abi::Thiscall, + Abi::Win64, + Abi::SysV64, + ], + + .. Default::default( ) + } + }) +} diff --git a/src/librustc_target/spec/xtensa_esp8266_none_elf.rs b/src/librustc_target/spec/xtensa_esp8266_none_elf.rs new file mode 100644 index 0000000000000..9b8b2fe63cffe --- /dev/null +++ b/src/librustc_target/spec/xtensa_esp8266_none_elf.rs @@ -0,0 +1,66 @@ +use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult, abi::Abi}; +// use crate::spec::abi::Abi; + +pub fn target() -> TargetResult { + Ok(Target { + llvm_target: "xtensa-none-elf".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:64-f64:64-a:0:32-n32".to_string(), + arch: "xtensa".to_string(), + target_os: "none".to_string(), + target_env: String::new(), + target_vendor: String::new(), + linker_flavor: LinkerFlavor::Gcc, + + options: TargetOptions { + executables: true, + cpu: "esp8266".to_string(), + // The LLVM backend currently can't generate object files. To + // workaround this LLVM generates assembly files which then we feed + // to gcc to get object files. For this reason we have a hard + // dependency on this specific gcc. + // asm_args: vec!["-mcpu=esp8266".to_string()], + linker: Some("xtensa-esp32-elf-gcc".to_string()), + no_integrated_as: true, + + max_atomic_width: Some(32), + atomic_cas: true, + + // Because these devices have very little resources having an + // unwinder is too onerous so we default to "abort" because the + // "unwind" strategy is very rare. + panic_strategy: PanicStrategy::Abort, + + // Similarly, one almost always never wants to use relocatable + // code because of the extra costs it involves. + relocation_model: "static".to_string(), + + // Right now we invoke an external assembler and this isn't + // compatible with multiple codegen units, and plus we probably + // don't want to invoke that many gcc instances. + default_codegen_units: Some(1), + + // Since MSP430 doesn't meaningfully support faulting on illegal + // instructions, LLVM generates a call to abort() function instead + // of a trap instruction. Such calls are 4 bytes long, and that is + // too much overhead for such small target. + trap_unreachable: false, + + // See the thumb_base.rs file for an explanation of this value + emit_debug_gdb_scripts: false, + + abi_blacklist: vec![ + Abi::Stdcall, + Abi::Fastcall, + Abi::Vectorcall, + Abi::Thiscall, + Abi::Win64, + Abi::SysV64, + ], + + .. Default::default( ) + } + }) +} From 76041e37dde5aa2a39e563337642102e8fa8fc51 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Fri, 31 May 2019 15:11:06 +0100 Subject: [PATCH 6/8] Update README.md --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 96d7e938be2f2..f3d45560dc630 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,10 @@ -# The Rust Programming Language +# The Rust Programming Language For Xtensa processors + +This fork enables projects to be built for the ESP32 and ESP8266 using [espressif's llvm fork](https://github.com/espressif/llvm-xtensa). The [esp-rs](https://github.com/esp-rs) organization has been formed to develop runtime, pac and hal crates for the esp32 and eventually esp8266. + +## Using this fork + +The [quickstart repo](https://github.com/MabezDev/xtensa-rust-quickstart) has more information on how to build this fork and use it to build xtensa compatible code. This is the main source code repository for [Rust]. It contains the compiler, standard library, and documentation. From 8e18ddbde93abd266b0d1470df15486f271325f6 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Thu, 25 Jul 2019 16:53:02 +0100 Subject: [PATCH 7/8] Merge pull request #3 from 0ndorio/fix/register_calculation Fix argument register calculation. Co-authored-by: rnd --- src/librustc_target/abi/call/xtensa.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/librustc_target/abi/call/xtensa.rs b/src/librustc_target/abi/call/xtensa.rs index 191470bd105a3..6a46b8a547141 100644 --- a/src/librustc_target/abi/call/xtensa.rs +++ b/src/librustc_target/abi/call/xtensa.rs @@ -20,18 +20,22 @@ fn classify_arg_ty(arg: &mut ArgType<'_, Ty>, xlen: u64, remaining_gpr: &mut // according to the ABI. 2*XLen-aligned varargs are passed in "aligned" // register pairs, so may consume 3 registers. - let mut stack_required = false; let arg_size = arg.layout.size; - let alignment = arg.layout.details.align.abi; - + if arg_size.bits() > MAX_ARG_IN_REGS_SIZE { + arg.make_indirect(); + return; + } + let alignment = arg.layout.details.align.abi; let mut required_gpr = 1u64; // at least one per arg + if alignment.bits() == 2 * xlen { required_gpr = 2 + (*remaining_gpr % 2); } else if arg_size.bits() > xlen && arg_size.bits() <= MAX_ARG_IN_REGS_SIZE { - required_gpr = arg_size.bits() + (xlen - 1) / xlen; + required_gpr = (arg_size.bits() + (xlen - 1)) / xlen; } + let mut stack_required = false; if required_gpr > *remaining_gpr { stack_required = true; required_gpr = *remaining_gpr; From dd8b6ad9c157fb7e6475ac5197b4c42f4da8e26e Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Mon, 11 Nov 2019 09:20:39 +0000 Subject: [PATCH 8/8] Merge pull request #10 from chocol4te/tidy_fix Fix tidy issues --- src/librustc_target/abi/call/xtensa.rs | 57 ++++++++----------- .../spec/xtensa_esp32_none_elf.rs | 6 +- .../spec/xtensa_esp8266_none_elf.rs | 6 +- src/librustc_target/spec/xtensa_none_elf.rs | 6 +- 4 files changed, 32 insertions(+), 43 deletions(-) diff --git a/src/librustc_target/abi/call/xtensa.rs b/src/librustc_target/abi/call/xtensa.rs index 6a46b8a547141..86a4c34781589 100644 --- a/src/librustc_target/abi/call/xtensa.rs +++ b/src/librustc_target/abi/call/xtensa.rs @@ -1,12 +1,11 @@ // reference: https://github.com/espressif/clang-xtensa/commit/6fb488d2553f06029e6611cf81c6efbd45b56e47#diff-aa74ae1e1ab6b7149789237edb78e688R8450 - use crate::abi::call::{ArgType, FnType, Reg, Uniform}; const NUM_ARG_GPR: u64 = 6; -const MAX_ARG_IN_REGS_SIZE: u64 = 4 * 32; +const MAX_ARG_IN_REGS_SIZE: u64 = 4 * 32; // const MAX_ARG_DIRECT_SIZE: u64 = MAX_ARG_IN_REGS_SIZE; -const MAX_RET_IN_REGS_SIZE: u64 = 2 * 32; +const MAX_RET_IN_REGS_SIZE: u64 = 2 * 32; fn classify_ret_ty(arg: &mut ArgType<'_, Ty>, xlen: u64) { // The rules for return and argument types are the same, so defer to @@ -14,12 +13,11 @@ fn classify_ret_ty(arg: &mut ArgType<'_, Ty>, xlen: u64) { classify_arg_ty(arg, xlen, &mut 2); // two as max return size } - fn classify_arg_ty(arg: &mut ArgType<'_, Ty>, xlen: u64, remaining_gpr: &mut u64) { // Determine the number of GPRs needed to pass the current argument // according to the ABI. 2*XLen-aligned varargs are passed in "aligned" // register pairs, so may consume 3 registers. - + let arg_size = arg.layout.size; if arg_size.bits() > MAX_ARG_IN_REGS_SIZE { arg.make_indirect(); @@ -31,7 +29,7 @@ fn classify_arg_ty(arg: &mut ArgType<'_, Ty>, xlen: u64, remaining_gpr: &mut if alignment.bits() == 2 * xlen { required_gpr = 2 + (*remaining_gpr % 2); - } else if arg_size.bits() > xlen && arg_size.bits() <= MAX_ARG_IN_REGS_SIZE { + } else if arg_size.bits() > xlen && arg_size.bits() <= MAX_ARG_IN_REGS_SIZE { required_gpr = (arg_size.bits() + (xlen - 1)) / xlen; } @@ -44,14 +42,16 @@ fn classify_arg_ty(arg: &mut ArgType<'_, Ty>, xlen: u64, remaining_gpr: &mut // if a value can fit in a reg and the // stack is not required, extend - if !arg.layout.is_aggregate() { // non-aggregate types + if !arg.layout.is_aggregate() { + // non-aggregate types if arg_size.bits() < xlen && !stack_required { arg.extend_integer_width_to(xlen); } - } else if arg_size.bits() as u64 <= MAX_ARG_IN_REGS_SIZE { // aggregate types + } else if arg_size.bits() as u64 <= MAX_ARG_IN_REGS_SIZE { + // aggregate types // Aggregates which are <= 4*32 will be passed in registers if possible, // so coerce to integers. - + // Use a single XLen int if possible, 2*XLen if 2*XLen alignment is // required, and a 2-element XLen array if only XLen alignment is // required. @@ -61,33 +61,26 @@ fn classify_arg_ty(arg: &mut ArgType<'_, Ty>, xlen: u64, remaining_gpr: &mut // arg.extend_integer_width_to(arg_size + (xlen - 1) / xlen); // } if alignment.bits() == 2 * xlen { - arg.cast_to(Uniform { - unit: Reg::i64(), - total: arg_size - }); + arg.cast_to(Uniform { unit: Reg::i64(), total: arg_size }); } else { - //TODO array type - this should be a homogenous array type + //FIXME array type - this should be a homogenous array type // arg.extend_integer_width_to(arg_size + (xlen - 1) / xlen); } - } else { // if we get here the stack is required assert!(stack_required); arg.make_indirect(); } - - // if arg_size as u64 <= MAX_ARG_IN_REGS_SIZE { - // let align = arg.layout.align.abi.bytes(); - // let total = arg.layout.size; - // arg.cast_to(Uniform { - // unit: if align <= 4 { Reg::i32() } else { Reg::i64() }, - // total - // }); - // return; - // } - - + // if arg_size as u64 <= MAX_ARG_IN_REGS_SIZE { + // let align = arg.layout.align.abi.bytes(); + // let total = arg.layout.size; + // arg.cast_to(Uniform { + // unit: if align <= 4 { Reg::i32() } else { Reg::i64() }, + // total + // }); + // return; + // } } pub fn compute_abi_info(fty: &mut FnType<'_, Ty>, xlen: u64) { @@ -95,14 +88,10 @@ pub fn compute_abi_info(fty: &mut FnType<'_, Ty>, xlen: u64) { classify_ret_ty(&mut fty.ret, xlen); } - let return_indirect = fty.ret.layout.size.bits() > MAX_RET_IN_REGS_SIZE || - fty.ret.is_indirect(); + let return_indirect = + fty.ret.layout.size.bits() > MAX_RET_IN_REGS_SIZE || fty.ret.is_indirect(); - let mut remaining_gpr = if return_indirect { - NUM_ARG_GPR - 1 - } else { - NUM_ARG_GPR - }; + let mut remaining_gpr = if return_indirect { NUM_ARG_GPR - 1 } else { NUM_ARG_GPR }; for arg in &mut fty.args { if arg.is_ignore() { diff --git a/src/librustc_target/spec/xtensa_esp32_none_elf.rs b/src/librustc_target/spec/xtensa_esp32_none_elf.rs index 8402f1a3663fa..b250a40e83950 100644 --- a/src/librustc_target/spec/xtensa_esp32_none_elf.rs +++ b/src/librustc_target/spec/xtensa_esp32_none_elf.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult, abi::Abi}; +use crate::spec::{abi::Abi, LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; // use crate::spec::abi::Abi; pub fn target() -> TargetResult { @@ -60,7 +60,7 @@ pub fn target() -> TargetResult { Abi::SysV64, ], - .. Default::default( ) - } + ..Default::default() + }, }) } diff --git a/src/librustc_target/spec/xtensa_esp8266_none_elf.rs b/src/librustc_target/spec/xtensa_esp8266_none_elf.rs index 9b8b2fe63cffe..2d9a70355cbfb 100644 --- a/src/librustc_target/spec/xtensa_esp8266_none_elf.rs +++ b/src/librustc_target/spec/xtensa_esp8266_none_elf.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult, abi::Abi}; +use crate::spec::{abi::Abi, LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; // use crate::spec::abi::Abi; pub fn target() -> TargetResult { @@ -60,7 +60,7 @@ pub fn target() -> TargetResult { Abi::SysV64, ], - .. Default::default( ) - } + ..Default::default() + }, }) } diff --git a/src/librustc_target/spec/xtensa_none_elf.rs b/src/librustc_target/spec/xtensa_none_elf.rs index afd043cf9047e..cb6811ad3d1ae 100644 --- a/src/librustc_target/spec/xtensa_none_elf.rs +++ b/src/librustc_target/spec/xtensa_none_elf.rs @@ -1,4 +1,4 @@ -use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult, abi::Abi}; +use crate::spec::{abi::Abi, LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; // use crate::spec::abi::Abi; pub fn target() -> TargetResult { @@ -60,7 +60,7 @@ pub fn target() -> TargetResult { Abi::SysV64, ], - .. Default::default( ) - } + ..Default::default() + }, }) }