Skip to content

Commit

Permalink
Merge pull request rust-lang#12 from chocol4te/xtensa_1.39
Browse files Browse the repository at this point in the history
Update to 1.39.0
  • Loading branch information
MabezDev authored Dec 7, 2019
2 parents 4560ea7 + dd8b6ad commit 4d9271c
Show file tree
Hide file tree
Showing 10 changed files with 328 additions and 2 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_llvm/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
7 changes: 7 additions & 0 deletions src/librustc_llvm/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,11 @@ pub fn initialize_available_targets() {
LLVMInitializeWebAssemblyTarget,
LLVMInitializeWebAssemblyTargetMC,
LLVMInitializeWebAssemblyAsmPrinter);
init_target!(llvm_component = "xtensa",
LLVMInitializeXtensaTargetInfo,
LLVMInitializeXtensaTarget,
LLVMInitializeXtensaTargetMC,
LLVMInitializeXtensaAsmPrinter,
LLVMInitializeXtensaAsmParser);

}
2 changes: 2 additions & 0 deletions src/librustc_target/abi/call/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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))
}

Expand Down
102 changes: 102 additions & 0 deletions src/librustc_target/abi/call/xtensa.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// 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<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<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();
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;
}

let mut stack_required = false;
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() {
// 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
// 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 {
//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;
// }
}

pub fn compute_abi_info<Ty>(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);
}
}
2 changes: 2 additions & 0 deletions src/librustc_target/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,8 @@ supported_targets! {
("thumbv8m.main-none-eabihf", thumbv8m_main_none_eabihf),

("msp430-none-elf", msp430_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),
Expand Down
66 changes: 66 additions & 0 deletions src/librustc_target/spec/xtensa_esp32_none_elf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use crate::spec::{abi::Abi, LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
// 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()
},
})
}
66 changes: 66 additions & 0 deletions src/librustc_target/spec/xtensa_esp8266_none_elf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use crate::spec::{abi::Abi, LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
// 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()
},
})
}
66 changes: 66 additions & 0 deletions src/librustc_target/spec/xtensa_none_elf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use crate::spec::{abi::Abi, LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
// 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()
},
})
}
9 changes: 9 additions & 0 deletions src/rustllvm/PassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand All @@ -185,6 +193,7 @@ void LLVMRustAddLastExtensionPasses(
SUBTARGET_SPARC \
SUBTARGET_HEXAGON \
SUBTARGET_RISCV \
SUBTARGET_XTENSA \

#define SUBTARGET(x) \
namespace llvm { \
Expand Down

0 comments on commit 4d9271c

Please sign in to comment.