#![allow(dead_code)]
use std::path::PathBuf;
use anyhow::Result;
use clap::{Parser, Subcommand, ValueEnum};
use crate::cuda_db;
use crate::migrate;
use crate::migrate::MigrateOptions;
use crate::parser;
use crate::walker;
#[derive(Debug, Parser)]
#[command(name = "decuda", version, about, long_about = None)]
pub struct Cli {
#[command(subcommand)]
pub command: Command,
}
#[derive(Debug, Subcommand)]
pub enum Command {
Migrate {
#[arg(short, long)]
input: PathBuf,
#[arg(short, long)]
output: PathBuf,
#[arg(short, long, value_enum, default_value_t = Target::All)]
target: Target,
#[arg(long)]
dry_run: bool,
#[arg(short, long)]
verbose: bool,
#[arg(long)]
filter: Option<String>,
},
Inspect {
#[arg(short, long)]
input: PathBuf,
#[arg(long)]
filter: Option<String>,
},
ListApis {
#[arg(short, long, value_enum)]
target: Option<Target>,
},
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, ValueEnum)]
pub enum Target {
Hip,
Sycl,
Rust,
Opencl,
All,
}
impl Target {
pub fn as_str(&self) -> &'static str {
match self {
Target::Hip => "hip",
Target::Sycl => "sycl",
Target::Rust => "rust",
Target::Opencl => "opencl",
Target::All => "all",
}
}
pub fn iter_real() -> [Target; 4] {
[Target::Hip, Target::Sycl, Target::Rust, Target::Opencl]
}
}
pub fn run() -> Result<()> {
let cli = Cli::parse();
match cli.command {
Command::Migrate {
input,
output,
target,
dry_run,
verbose,
filter,
} => {
let opts = MigrateOptions {
input,
output,
target,
dry_run,
verbose,
filter,
};
let report = migrate::run(opts)?;
crate::report::write_human_report(&report);
if report.has_errors() {
anyhow::bail!("migration completed with errors; see report");
}
Ok(())
}
Command::Inspect { input, filter } => {
let files = walker::collect_cuda_files(&input, filter.as_deref())?;
for path in files {
println!("==> {}", path.display());
let unit = parser::translate_path(&path)?;
unit.print_summary();
}
Ok(())
}
Command::ListApis { target } => {
let db = cuda_db::database();
let entries: std::collections::BTreeMap<_, _> = db.iter().collect();
for (cuda_name, info) in &entries {
if let Some(t) = target {
if !info.supports(t) {
continue;
}
}
println!("{:<36} {}", cuda_name, info.summarize(target.unwrap_or(Target::All)));
}
Ok(())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn iter_real_has_four_backends() {
assert_eq!(Target::iter_real().len(), 4);
}
#[test]
fn target_str_unique() {
let s: std::collections::HashSet<_> =
Target::iter_real().iter().map(|t| t.as_str()).collect();
assert_eq!(s.len(), 4);
}
}