corosensei 0.1.4

A fast and safe implementation of stackful coroutines
Documentation
//! Special build-time detection for ARM targets.
//!
//! We need to determine some properties of the target for inline assembly that
//! are not otherwise easily available. Specifically:
//! - Does the target use the ARM or Thumb instruction set by default?
//! - Does the target support Thumb2?
//! - Does the target use R7 or R11 for its frame pointer?
//! - Does the target treat R9 as a reserved register?

use std::env;

fn main() {
    println!("cargo:rerun-if-changed=build.rs");

    // We only care about ARM.
    let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
    if arch != "arm" {
        return;
    }

    // Probe some registers using asm! to see if they are reserved.
    let cfg = autocfg::new();
    let r7_available = cfg.probe_expression("unsafe { core::arch::asm!(\"\", out(\"r7\") _) }");
    let r9_available = cfg.probe_expression("unsafe { core::arch::asm!(\"\", out(\"r9\") _) }");
    let r11_available = cfg.probe_expression("unsafe { core::arch::asm!(\"\", out(\"r11\") _) }");

    if !r9_available {
        autocfg::emit("r9_reserved");
    }

    match (r7_available, r11_available) {
        (true, false) => {}
        (false, true) => autocfg::emit("fp_is_r7"),
        _ => panic!("could not determine whether frame pointer is r7 or r11"),
    }

    // The most reliable way is to check for the thumb-mode feature in
    // CARGO_CFG_TARGET_FEATURE but this is only available on nightly. As a
    // fallback we just check if the target name starts with "thumb".
    let (is_thumb, has_thumb2) = if let Ok(target_features) = env::var("CARGO_CFG_TARGET_FEATURE") {
        (
            target_features.split(',').any(|s| s == "thumb-mode"),
            target_features.split(',').any(|s| s == "thumb2"),
        )
    } else {
        // thumbv6m-none-eabi is the only thumb target that doesn't support
        // thumb2.
        let target = env::var("TARGET").unwrap();
        (target.starts_with("thumb"), !target.starts_with("thumbv6"))
    };
    if is_thumb {
        autocfg::emit("is_thumb");
    }
    if has_thumb2 {
        autocfg::emit("has_thumb2");
    }
}