Skip to content
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

Compile for esp32(s2,c3,..) #20

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -23,6 +23,10 @@ c2rust-bitfields = { version = "0.3", features = ["no_std"] }
riot-build = { version = "< 0.2.0", optional = true }
riot-rs-core = { version = "< 0.2.0", optional = true }

# atomic support
portable-atomic = {version = "1.0.1", features = ["critical-section"]}
critical-section = {version = "1.1.1", features = ["restore-state-bool"], optional = true}

[build-dependencies]
bindgen = "^0.60.1"
shlex = "^1"
@@ -36,5 +40,12 @@ regex = "1"
# `extern_types`.
keep-extern-types = []

# This prevents the `undef` of the dummy atomic definitions in
# `riot-c2rust.h` in case `stdatomic.h` is somewhere included.
# Note that these definitions are not realy atomics but placeholders.
# Thus a programm relying on the atomicity of the transpiled Rust structs
# will probably not work as intended.
dummy-atomic-definitions = []

# this needs to be set to build together with RIOT-rs.
riot-rs = [ "riot-build", "riot-rs-core", "keep-extern-types" ]
41 changes: 36 additions & 5 deletions build.rs
Original file line number Diff line number Diff line change
@@ -61,6 +61,14 @@ fn main() {
let mut consensus_cflag_groups: Option<Vec<Vec<&str>>> = None;
for entry in parsed.iter() {
if let Some(consensus_cc) = consensus_cc.as_ref() {
// Prevent c++ flags from beeing used.
// For example esp32 uses C++ internally.
// Since bindings to C++ are not supported by C2Rust
// we can savely kick it out anyway.
if entry.arguments[0] == "clang++" {
continue;
}

assert!(consensus_cc == &entry.arguments[0])
} else {
consensus_cc = Some(&entry.arguments[0]);
@@ -367,8 +375,16 @@ fn main() {

let arguments: Vec<_> = core::iter::once("any-cc".to_string())
.chain(cflags.into_iter())
.chain({
if cfg!(feature = "dummy-atomic-definitions") {
vec!["-DDUMMY_ATOMICS=1".to_string()]
} else {
vec![]
}
})
.chain(core::iter::once(c2rust_infile.to_string()))
.collect();

let compile_commands = json!([{
"arguments": arguments,
"directory": out_path,
@@ -447,11 +463,26 @@ fn main() {
if env::var("CARGO_FEATURE_KEEP_EXTERN_TYPES").is_err() {
// There's only one `pub type` usually, and that breaks use on stable, and src/inline.rs has a
// workaround for that
rustcode = rustcode.replace("\n pub type __locale_t;", "");
rustcode = rustcode.replace("\n pub type _IO_wide_data;", "");
rustcode = rustcode.replace("\n pub type _IO_codecvt;", "");
rustcode = rustcode.replace("\n pub type _IO_marker;", "");
rustcode = rustcode.replace("\n pub type __lock;", "");
let replacements = [
("\n pub type __locale_t;", ""),
("\n pub type _IO_wide_data;", ""),
("\n pub type _IO_codecvt;", ""),
("\n pub type _IO_marker;", ""),
("\n pub type __lock;", ""),
];

let mut old_len = rustcode.len();

for (reg, repl) in replacements {
rustcode = rustcode.replace(reg, repl);

if rustcode.len() != old_len {
eprintln!("Could not remove {reg} from generated rustcode.\
This might lead to duplicate definitions. Consider using cargo feature \"keep-extern-types\" if this causes problems")
}

old_len = rustcode.len();
}
}

// Replace the function declarations with ... usually something pub, but special considerations
14 changes: 10 additions & 4 deletions riot-c2rust.h
Original file line number Diff line number Diff line change
@@ -12,10 +12,12 @@
#define __builtin_arm_get_fpscr __masked_builtin_arm_get_fpscr
#define __builtin_arm_set_fpscr __masked_builtin_arm_set_fpscr
extern int missing_implementation_for_fpscr_in_c2rust_see_issue_345;
static inline int __masked_builtin_arm_get_fpscr(void) {
static inline int __masked_builtin_arm_get_fpscr(void)
{
return missing_implementation_for_fpscr_in_c2rust_see_issue_345;
}
static inline void __masked_builtin_arm_set_fpscr(int fpscr){
static inline void __masked_builtin_arm_set_fpscr(int fpscr)
{
missing_implementation_for_fpscr_in_c2rust_see_issue_345 = fpscr;
}

@@ -28,8 +30,8 @@ static inline void __masked_builtin_arm_set_fpscr(int fpscr){
//
// Proper fix: resolve https://github.com/immunant/c2rust/issues/293
#define __CLANG_STDATOMIC_H // for clang
#define _STDATOMIC_H // for GCC
#define _STDATOMIC_H_ // for newlib
#define _STDATOMIC_H // for GCC
#define _STDATOMIC_H_ // for newlib
#define ATOMIC_VAR_INIT(x) x
// FIXME for all: is it really? We don't rely on it, see below on the explicitly included files.
#define atomic_bool bool
@@ -94,6 +96,9 @@ static inline void __masked_builtin_arm_set_fpscr(int fpscr){
// Exported Clang AST was invalid. Check warnings above for unimplemented features.
// --> /usr/lib/gcc/arm-none-eabi/10.3.1/include/stdatomic.h:69:1
// [-Wclang-ast]
//
// undefs can be disabled by using cargo feature: "dummy-atomic-definitions"
#ifndef DUMMY_ATOMICS
#undef __CLANG_STDATOMIC_H
#undef _STDATOMIC_H_
#undef _STDATOMIC_H
@@ -135,6 +140,7 @@ static inline void __masked_builtin_arm_set_fpscr(int fpscr){
#undef atomic_ptrdiff_t
#undef atomic_intmax_t
#undef atomic_uintmax_t
#endif

// Allow header files that pull in lots of odd stuff but don't depend on
// inlines -- like nimble's host/ble_gap.h -- to opt out of C2Rust altogether
38 changes: 38 additions & 0 deletions src/critical_section.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//! [`critical_section`] implementation for **single core cpu boards**
//! using RIOTs interrupts interface. (Just disables interrupts).
//!
//! This is needed by [`portable_atomic`] to provide atomics to boards without hardware
//! support or rather where rust does not support atomics.

use critical_section::RawRestoreState;

struct RIOTCriticalSection;

critical_section::set_impl!(RIOTCriticalSection);

unsafe impl critical_section::Impl for RIOTCriticalSection {
unsafe fn acquire() -> RawRestoreState {
if crate::irq_is_in() {
return false;
}

let disabled = crate::irq_is_enabled();
// It is possible that between here an interrupt
// interferes and causes another thread/process to continue.
// This should not be a problem because:
// Szenario 1: The other process does not enter a critical section
// or disables interrupts and nothing happens.
// Szenario 2: The other process does disable interrupts, but
// then this thread here can only continue once the interrupts are back on
// and one causes this thread to continue.
// In both cases we should not face a toctu problem.
crate::irq_disable();
disabled
}

unsafe fn release(token: RawRestoreState) {
if token {
crate::irq_enable();
}
}
}
2 changes: 1 addition & 1 deletion src/intrinsics_replacements.rs
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
//! (But then again, they're not needed, as theire RIOT C code can't contain these operations).

#[cfg(target_arch = "riscv32")]
use core::sync::atomic::{AtomicU32, Ordering};
use portable_atomic::{AtomicU32, Ordering};

#[cfg(target_arch = "riscv32")]
pub(crate) fn atomic_and_relaxed(dst: *mut u32, src: u32) -> u32 {
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -110,6 +110,8 @@ pub mod libc;

mod intrinsics_replacements;

mod critical_section;

mod bindgen;
pub mod inline;