zoc: Improve error messages

This commit is contained in:
Joëlle van Essen 2025-03-27 11:29:21 +01:00
parent e6e9a79fe7
commit 69080d2abc
No known key found for this signature in database
GPG key ID: 28D3B5CDD4B43882
6 changed files with 107 additions and 56 deletions

27
Cargo.lock generated
View file

@ -820,8 +820,8 @@ dependencies = [
"ptx_parser", "ptx_parser",
"quick-error", "quick-error",
"rustc-hash 2.0.0", "rustc-hash 2.0.0",
"strum", "strum 0.26.3",
"strum_macros", "strum_macros 0.26.4",
"tempfile", "tempfile",
"thiserror 1.0.64", "thiserror 1.0.64",
"unwrap_or", "unwrap_or",
@ -836,6 +836,7 @@ dependencies = [
"logos", "logos",
"ptx_parser_macros", "ptx_parser_macros",
"rustc-hash 2.0.0", "rustc-hash 2.0.0",
"strum 0.27.1",
"thiserror 1.0.64", "thiserror 1.0.64",
"winnow", "winnow",
] ]
@ -1047,6 +1048,15 @@ version = "0.26.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
[[package]]
name = "strum"
version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32"
dependencies = [
"strum_macros 0.27.1",
]
[[package]] [[package]]
name = "strum_macros" name = "strum_macros"
version = "0.26.4" version = "0.26.4"
@ -1060,6 +1070,19 @@ dependencies = [
"syn 2.0.89", "syn 2.0.89",
] ]
[[package]]
name = "strum_macros"
version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.89",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.109" version = "1.0.109"

View file

@ -1,6 +1,5 @@
use std::ffi::FromBytesUntilNulError; use std::ffi::FromBytesUntilNulError;
use std::io; use std::io;
use std::path::PathBuf;
use std::str::Utf8Error; use std::str::Utf8Error;
use amd_comgr_sys::amd_comgr_status_s; use amd_comgr_sys::amd_comgr_status_s;
@ -10,22 +9,20 @@ use ptx_parser::PtxError;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum CompilerError { pub enum CompilerError {
#[error("HIP error: {0:?}")] #[error("HIP error code: {0:?}")]
HipError(hipErrorCode_t), HipError(hipErrorCode_t),
#[error("amd_comgr error: {0:?}")] #[error("amd_comgr status code: {0:?}")]
ComgrError(amd_comgr_status_s), ComgrError(amd_comgr_status_s),
#[error("Not a regular file: {0}")] #[error(transparent)]
CheckPathError(PathBuf), IoError(#[from] io::Error),
#[error("Invalid output type: {0}")] #[error(transparent)]
ParseOutputTypeError(String), Utf8Error(#[from] Utf8Error),
#[error("Error translating PTX: {0:?}")] #[error("{message}")]
PtxTranslateError(TranslateError), GenericError {
#[error("IO error: {0:?}")] #[source]
IoError(io::Error), cause: Option<Box<dyn std::error::Error>>,
#[error("Error parsing file: {0:?}")] message: String,
ParseFileError(Utf8Error), },
#[error("Error: {0}")]
GenericError(String)
} }
impl From<hipErrorCode_t> for CompilerError { impl From<hipErrorCode_t> for CompilerError {
@ -42,32 +39,37 @@ impl From<amd_comgr_status_s> for CompilerError {
impl From<Vec<PtxError<'_>>> for CompilerError { impl From<Vec<PtxError<'_>>> for CompilerError {
fn from(causes: Vec<PtxError>) -> Self { fn from(causes: Vec<PtxError>) -> Self {
let errors: Vec<String> = causes.iter().map(PtxError::to_string).collect(); let errors: Vec<String> = causes
let msg = errors.join("\n"); .iter()
CompilerError::GenericError(msg) .map(|e| {
} let msg = match e {
} PtxError::UnrecognizedStatement(value)
| PtxError::UnrecognizedDirective(value) => value.unwrap_or("").to_string(),
impl From<io::Error> for CompilerError { other => other.to_string(),
fn from(cause: io::Error) -> Self { };
CompilerError::IoError(cause) format!("PtxError::{}: {}", e.as_ref(), msg)
} })
} .collect();
let message = errors.join("\n");
impl From<Utf8Error> for CompilerError { CompilerError::GenericError {
fn from(cause: Utf8Error) -> Self { cause: None,
CompilerError::ParseFileError(cause) message,
}
} }
} }
impl From<TranslateError> for CompilerError { impl From<TranslateError> for CompilerError {
fn from(cause: TranslateError) -> Self { fn from(cause: TranslateError) -> Self {
CompilerError::PtxTranslateError(cause) let message = format!("PTX TranslateError::{}", cause.as_ref());
let cause = Some(Box::new(cause) as Box<dyn std::error::Error>);
CompilerError::GenericError { cause, message }
} }
} }
impl From<FromBytesUntilNulError> for CompilerError { impl From<FromBytesUntilNulError> for CompilerError {
fn from(cause: FromBytesUntilNulError) -> Self { fn from(cause: FromBytesUntilNulError) -> Self {
CompilerError::GenericError(format!("{}", cause)) let message = format!("{}", cause);
let cause = Some(Box::new(cause) as Box<dyn std::error::Error>);
CompilerError::GenericError { cause, message }
} }
} }

View file

@ -1,9 +1,11 @@
use std::env; use std::env;
use std::error::Error;
use std::ffi::{CStr, CString, OsStr}; use std::ffi::{CStr, CString, OsStr};
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::{self, Write}; use std::io::{self, Write};
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::ExitCode;
use std::str::{self, FromStr}; use std::str::{self, FromStr};
use bpaf::Bpaf; use bpaf::Bpaf;
@ -26,7 +28,17 @@ pub struct Options {
ptx_path: String, ptx_path: String,
} }
fn main() -> Result<(), CompilerError> { fn main() -> ExitCode {
main_core().map_or_else(
|e| {
eprintln!("Error: {}", e);
ExitCode::FAILURE
},
|_| ExitCode::SUCCESS,
)
}
fn main_core() -> Result<(), CompilerError> {
let opts = options().run(); let opts = options().run();
let output_type = opts.output_type.unwrap_or_default(); let output_type = opts.output_type.unwrap_or_default();
@ -36,7 +48,7 @@ fn main() -> Result<(), CompilerError> {
let output_path = match opts.output_path { let output_path = match opts.output_path {
Some(value) => value, Some(value) => value,
None => get_output_path(&ptx_path, &output_type)? None => get_output_path(&ptx_path, &output_type)?,
}; };
check_path(&output_path)?; check_path(&output_path)?;
@ -48,7 +60,7 @@ fn main() -> Result<(), CompilerError> {
OutputType::LlvmIrPreLinked => llvm.llvm_ir, OutputType::LlvmIrPreLinked => llvm.llvm_ir,
OutputType::LlvmIrLinked => get_linked_bitcode(&llvm)?, OutputType::LlvmIrLinked => get_linked_bitcode(&llvm)?,
OutputType::Elf => get_elf(&llvm)?, OutputType::Elf => get_elf(&llvm)?,
OutputType::Assembly => get_assembly(&llvm)? OutputType::Assembly => get_assembly(&llvm)?,
}; };
write_to_file(&output, &output_path).map_err(CompilerError::from)?; write_to_file(&output, &output_path).map_err(CompilerError::from)?;
@ -56,7 +68,7 @@ fn main() -> Result<(), CompilerError> {
} }
fn ptx_to_llvm(ptx: &str) -> Result<LLVMArtifacts, CompilerError> { fn ptx_to_llvm(ptx: &str) -> Result<LLVMArtifacts, CompilerError> {
let ast = ptx_parser::parse_module_checked(ptx).map_err(CompilerError::from).map_err(CompilerError::from)?; let ast = ptx_parser::parse_module_checked(ptx).map_err(CompilerError::from)?;
let module = ptx::to_llvm_module(ast).map_err(CompilerError::from)?; let module = ptx::to_llvm_module(ast).map_err(CompilerError::from)?;
let bitcode = module.llvm_ir.write_bitcode_to_memory().to_vec(); let bitcode = module.llvm_ir.write_bitcode_to_memory().to_vec();
let linked_bitcode = module.linked_bitcode().to_vec(); let linked_bitcode = module.linked_bitcode().to_vec();
@ -82,7 +94,11 @@ fn get_arch() -> Result<CString, CompilerError> {
unsafe { hipGetDevicePropertiesR0600(dev_props.as_mut_ptr(), 0) }?; unsafe { hipGetDevicePropertiesR0600(dev_props.as_mut_ptr(), 0) }?;
let dev_props = unsafe { dev_props.assume_init() }; let dev_props = unsafe { dev_props.assume_init() };
let arch = dev_props.gcnArchName; let arch = dev_props.gcnArchName;
let arch: Vec<u8> = arch.to_vec().iter().map(|&v| i8::to_ne_bytes(v)[0]).collect(); let arch: Vec<u8> = arch
.to_vec()
.iter()
.map(|&v| i8::to_ne_bytes(v)[0])
.collect();
let arch = CStr::from_bytes_until_nul(arch.as_slice())?; let arch = CStr::from_bytes_until_nul(arch.as_slice())?;
Ok(CString::from(arch)) Ok(CString::from(arch))
} }
@ -94,26 +110,29 @@ fn get_linked_bitcode(llvm: &LLVMArtifacts) -> Result<Vec<u8>, CompilerError> {
fn get_elf(llvm: &LLVMArtifacts) -> Result<Vec<u8>, CompilerError> { fn get_elf(llvm: &LLVMArtifacts) -> Result<Vec<u8>, CompilerError> {
let arch = get_arch()?; let arch = get_arch()?;
comgr::get_executable_as_bytes(&arch, &llvm.bitcode, &llvm.linked_bitcode).map_err(CompilerError::from) comgr::get_executable_as_bytes(&arch, &llvm.bitcode, &llvm.linked_bitcode)
.map_err(CompilerError::from)
} }
fn get_assembly(llvm: &LLVMArtifacts) -> Result<Vec<u8>, CompilerError> { fn get_assembly(llvm: &LLVMArtifacts) -> Result<Vec<u8>, CompilerError> {
let arch = get_arch()?; let arch = get_arch()?;
comgr::get_assembly_as_bytes(&arch, &llvm.bitcode, &llvm.linked_bitcode).map_err(CompilerError::from) comgr::get_assembly_as_bytes(&arch, &llvm.bitcode, &llvm.linked_bitcode)
.map_err(CompilerError::from)
} }
fn check_path(path: &Path) -> Result<(), CompilerError> { fn check_path(path: &Path) -> Result<(), CompilerError> {
if path.try_exists().map_err(CompilerError::from)? && !path.is_file() { if path.try_exists().map_err(CompilerError::from)? && !path.is_file() {
let error = CompilerError::CheckPathError(path.to_path_buf()); let message = format!("Not a regular file: {:?}", path.to_path_buf());
let error = CompilerError::GenericError {
cause: None,
message,
};
return Err(error); return Err(error);
} }
Ok(()) Ok(())
} }
fn get_output_path( fn get_output_path(ptx_path: &PathBuf, output_type: &OutputType) -> Result<PathBuf, CompilerError> {
ptx_path: &PathBuf,
output_type: &OutputType,
) -> Result<PathBuf, CompilerError> {
let current_dir = env::current_dir().map_err(CompilerError::from)?; let current_dir = env::current_dir().map_err(CompilerError::from)?;
let output_path = current_dir.join( let output_path = current_dir.join(
ptx_path ptx_path
@ -169,7 +188,13 @@ impl FromStr for OutputType {
"ll_linked" => Ok(Self::LlvmIrLinked), "ll_linked" => Ok(Self::LlvmIrLinked),
"elf" => Ok(Self::Elf), "elf" => Ok(Self::Elf),
"asm" => Ok(Self::Assembly), "asm" => Ok(Self::Assembly),
_ => Err(CompilerError::ParseOutputTypeError(s.into())), _ => {
let message = format!("Not a valid output type: {}", s);
Err(CompilerError::GenericError {
cause: None,
message,
})
}
} }
} }
} }

View file

@ -17,8 +17,8 @@ mod expand_operands;
mod fix_special_registers2; mod fix_special_registers2;
mod hoist_globals; mod hoist_globals;
mod insert_explicit_load_store; mod insert_explicit_load_store;
mod instruction_mode_to_global_mode;
mod insert_implicit_conversions2; mod insert_implicit_conversions2;
mod instruction_mode_to_global_mode;
mod normalize_basic_blocks; mod normalize_basic_blocks;
mod normalize_identifiers2; mod normalize_identifiers2;
mod normalize_predicates2; mod normalize_predicates2;
@ -31,7 +31,7 @@ static ZLUDA_PTX_IMPL: &'static [u8] = include_bytes!("../../lib/zluda_ptx_impl.
const ZLUDA_PTX_PREFIX: &'static str = "__zluda_ptx_impl_"; const ZLUDA_PTX_PREFIX: &'static str = "__zluda_ptx_impl_";
quick_error! { quick_error! {
#[derive(Debug)] #[derive(Debug, strum_macros::AsRefStr)]
pub enum TranslateError { pub enum TranslateError {
UnknownSymbol {} UnknownSymbol {}
UntypedSymbol {} UntypedSymbol {}

View file

@ -7,11 +7,12 @@ edition = "2021"
[lib] [lib]
[dependencies] [dependencies]
bitflags = "1.2"
derive_more = { version = "1", features = ["display"] }
logos = "0.14" logos = "0.14"
ptx_parser_macros = { path = "../ptx_parser_macros" }
rustc-hash = "2.0.0"
strum = { version = "0.27.1", features = ["derive"] }
thiserror = "1.0"
winnow = { version = "0.6.18" } winnow = { version = "0.6.18" }
#winnow = { version = "0.6.18", features = ["debug"] } #winnow = { version = "0.6.18", features = ["debug"] }
ptx_parser_macros = { path = "../ptx_parser_macros" }
thiserror = "1.0"
bitflags = "1.2"
rustc-hash = "2.0.0"
derive_more = { version = "1", features = ["display"] }

View file

@ -1240,7 +1240,7 @@ impl<Ident> ast::ParsedOperand<Ident> {
} }
} }
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error, strum::AsRefStr)]
pub enum PtxError<'input> { pub enum PtxError<'input> {
#[error("{source}")] #[error("{source}")]
ParseInt { ParseInt {