Skip to content

Update to 1.39.0 #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Dec 7, 2019
Merged
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