mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-08-02 14:19:57 +00:00
zoc: Linked LLVM IR
This commit is contained in:
parent
87b30a6604
commit
06328891c4
5 changed files with 170 additions and 68 deletions
|
@ -1,7 +1,9 @@
|
||||||
use amd_comgr_sys::*;
|
use amd_comgr_sys::*;
|
||||||
use std::{ffi::CStr, mem, ptr};
|
use std::ffi::CStr;
|
||||||
|
use std::mem;
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
struct Data(amd_comgr_data_t);
|
pub struct Data(amd_comgr_data_t);
|
||||||
|
|
||||||
impl Data {
|
impl Data {
|
||||||
fn new(
|
fn new(
|
||||||
|
@ -20,7 +22,7 @@ impl Data {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_content(&self) -> Result<Vec<u8>, amd_comgr_status_s> {
|
pub fn copy_content(&self) -> Result<Vec<u8>, amd_comgr_status_s> {
|
||||||
let mut size = unsafe { mem::zeroed() };
|
let mut size = unsafe { mem::zeroed() };
|
||||||
unsafe { amd_comgr_get_data(self.get(), &mut size, ptr::null_mut()) }?;
|
unsafe { amd_comgr_get_data(self.get(), &mut size, ptr::null_mut()) }?;
|
||||||
let mut result: Vec<u8> = Vec::with_capacity(size);
|
let mut result: Vec<u8> = Vec::with_capacity(size);
|
||||||
|
@ -30,7 +32,7 @@ impl Data {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DataSet(amd_comgr_data_set_t);
|
pub struct DataSet(amd_comgr_data_set_t);
|
||||||
|
|
||||||
impl DataSet {
|
impl DataSet {
|
||||||
fn new() -> Result<Self, amd_comgr_status_s> {
|
fn new() -> Result<Self, amd_comgr_status_s> {
|
||||||
|
@ -47,7 +49,7 @@ impl DataSet {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_data(
|
pub fn get_data(
|
||||||
&self,
|
&self,
|
||||||
kind: amd_comgr_data_kind_t,
|
kind: amd_comgr_data_kind_t,
|
||||||
index: usize,
|
index: usize,
|
||||||
|
@ -108,11 +110,10 @@ impl Drop for ActionInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_bitcode(
|
pub fn link_bitcode(
|
||||||
gcn_arch: &CStr,
|
|
||||||
main_buffer: &[u8],
|
main_buffer: &[u8],
|
||||||
ptx_impl: &[u8],
|
ptx_impl: &[u8],
|
||||||
) -> Result<Vec<u8>, amd_comgr_status_s> {
|
) -> Result<DataSet, amd_comgr_status_s> {
|
||||||
use amd_comgr_sys::*;
|
use amd_comgr_sys::*;
|
||||||
let bitcode_data_set = DataSet::new()?;
|
let bitcode_data_set = DataSet::new()?;
|
||||||
let main_bitcode_data = Data::new(
|
let main_bitcode_data = Data::new(
|
||||||
|
@ -128,11 +129,21 @@ pub fn compile_bitcode(
|
||||||
)?;
|
)?;
|
||||||
bitcode_data_set.add(&stdlib_bitcode_data)?;
|
bitcode_data_set.add(&stdlib_bitcode_data)?;
|
||||||
let linking_info = ActionInfo::new()?;
|
let linking_info = ActionInfo::new()?;
|
||||||
let linked_data_set = do_action(
|
do_action(
|
||||||
&bitcode_data_set,
|
&bitcode_data_set,
|
||||||
&linking_info,
|
&linking_info,
|
||||||
amd_comgr_action_kind_t::AMD_COMGR_ACTION_LINK_BC_TO_BC,
|
amd_comgr_action_kind_t::AMD_COMGR_ACTION_LINK_BC_TO_BC,
|
||||||
)?;
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compile_bitcode(
|
||||||
|
gcn_arch: &CStr,
|
||||||
|
main_buffer: &[u8],
|
||||||
|
ptx_impl: &[u8],
|
||||||
|
) -> Result<Vec<u8>, amd_comgr_status_s> {
|
||||||
|
use amd_comgr_sys::*;
|
||||||
|
|
||||||
|
let linked_data_set = link_bitcode(main_buffer, ptx_impl)?;
|
||||||
let compile_to_exec = ActionInfo::new()?;
|
let compile_to_exec = ActionInfo::new()?;
|
||||||
compile_to_exec.set_isa_name(gcn_arch)?;
|
compile_to_exec.set_isa_name(gcn_arch)?;
|
||||||
compile_to_exec.set_language(amd_comgr_language_t::AMD_COMGR_LANGUAGE_LLVM_IR)?;
|
compile_to_exec.set_language(amd_comgr_language_t::AMD_COMGR_LANGUAGE_LLVM_IR)?;
|
||||||
|
|
|
@ -2,5 +2,5 @@ pub(crate) mod pass;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
pub use pass::to_llvm_module;
|
pub use pass::{TranslateError, to_llvm_module};
|
||||||
|
pub use pass::emit_llvm::bitcode_to_ir;
|
|
@ -27,11 +27,13 @@
|
||||||
use std::array::TryFromSliceError;
|
use std::array::TryFromSliceError;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::ffi::{CStr, NulError};
|
use std::ffi::{CStr, NulError};
|
||||||
|
use std::mem::MaybeUninit;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::{i8, ptr};
|
use std::ptr;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use llvm_zluda::analysis::{LLVMVerifierFailureAction, LLVMVerifyModule};
|
use llvm_zluda::analysis::{LLVMVerifierFailureAction, LLVMVerifyModule};
|
||||||
|
use llvm_zluda::bit_reader::LLVMParseBitcodeInContext2;
|
||||||
use llvm_zluda::bit_writer::LLVMWriteBitcodeToMemoryBuffer;
|
use llvm_zluda::bit_writer::LLVMWriteBitcodeToMemoryBuffer;
|
||||||
use llvm_zluda::{core::*, *};
|
use llvm_zluda::{core::*, *};
|
||||||
use llvm_zluda::{prelude::*, LLVMZludaBuildAtomicRMW};
|
use llvm_zluda::{prelude::*, LLVMZludaBuildAtomicRMW};
|
||||||
|
@ -118,6 +120,24 @@ impl Drop for Module {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<MemoryBuffer> for Module {
|
||||||
|
fn from(memory_buffer: MemoryBuffer) -> Self {
|
||||||
|
let context = Context::new();
|
||||||
|
let mut module: MaybeUninit<LLVMModuleRef> = MaybeUninit::uninit();
|
||||||
|
unsafe {
|
||||||
|
LLVMParseBitcodeInContext2(context.get(), memory_buffer.get(), module.as_mut_ptr());
|
||||||
|
}
|
||||||
|
let module = unsafe { module.assume_init() };
|
||||||
|
Self(module, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bitcode_to_ir(bitcode: Vec<u8>) -> Vec<u8> {
|
||||||
|
let memory_buffer: MemoryBuffer = bitcode.into();
|
||||||
|
let module: Module = memory_buffer.into();
|
||||||
|
module.print_module_to_string().to_bytes().to_vec()
|
||||||
|
}
|
||||||
|
|
||||||
struct Builder(LLVMBuilderRef);
|
struct Builder(LLVMBuilderRef);
|
||||||
|
|
||||||
impl Builder {
|
impl Builder {
|
||||||
|
@ -170,6 +190,12 @@ impl Message {
|
||||||
|
|
||||||
pub struct MemoryBuffer(LLVMMemoryBufferRef);
|
pub struct MemoryBuffer(LLVMMemoryBufferRef);
|
||||||
|
|
||||||
|
impl MemoryBuffer {
|
||||||
|
fn get(&self) -> LLVMMemoryBufferRef {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Drop for MemoryBuffer {
|
impl Drop for MemoryBuffer {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -188,6 +214,26 @@ impl Deref for MemoryBuffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Vec<i8>> for MemoryBuffer {
|
||||||
|
fn from(value: Vec<i8>) -> Self {
|
||||||
|
let memory_buffer: LLVMMemoryBufferRef = unsafe {
|
||||||
|
LLVMCreateMemoryBufferWithMemoryRangeCopy(
|
||||||
|
value.as_ptr(),
|
||||||
|
value.len(),
|
||||||
|
ptr::null()
|
||||||
|
)
|
||||||
|
};
|
||||||
|
Self(memory_buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec<u8>> for MemoryBuffer {
|
||||||
|
fn from(value: Vec<u8>) -> Self {
|
||||||
|
let value: Vec<i8> = value.iter().map(|&v| i8::from_ne_bytes([v])).collect();
|
||||||
|
value.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn run<'input>(
|
pub(super) fn run<'input>(
|
||||||
id_defs: GlobalStringIdentResolver2<'input>,
|
id_defs: GlobalStringIdentResolver2<'input>,
|
||||||
directives: Vec<Directive2<ast::Instruction<SpirvWord>, SpirvWord>>,
|
directives: Vec<Directive2<ast::Instruction<SpirvWord>, SpirvWord>>,
|
||||||
|
|
66
zoc/src/error.rs
Normal file
66
zoc/src/error.rs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
use std::io;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::str::Utf8Error;
|
||||||
|
|
||||||
|
use amd_comgr_sys::amd_comgr_status_s;
|
||||||
|
use hip_runtime_sys::hipErrorCode_t;
|
||||||
|
use ptx::TranslateError;
|
||||||
|
use ptx_parser::PtxError;
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum CompilerError {
|
||||||
|
#[error("HIP error: {0:?}")]
|
||||||
|
HipError(hipErrorCode_t),
|
||||||
|
#[error("amd_comgr error: {0:?}")]
|
||||||
|
ComgrError(amd_comgr_status_s),
|
||||||
|
#[error("Not a regular file: {0}")]
|
||||||
|
CheckPathError(PathBuf),
|
||||||
|
#[error("Invalid output type: {0}")]
|
||||||
|
ParseOutputTypeError(String),
|
||||||
|
#[error("Error parsing PTX: {0}")]
|
||||||
|
PtxParserError(String),
|
||||||
|
#[error("Error translating PTX: {0:?}")]
|
||||||
|
PtxTranslateError(TranslateError),
|
||||||
|
#[error("IO error: {0:?}")]
|
||||||
|
IoError(io::Error),
|
||||||
|
#[error("Error parsing file: {0:?}")]
|
||||||
|
ParseFileError(Utf8Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<hipErrorCode_t> for CompilerError {
|
||||||
|
fn from(error_code: hipErrorCode_t) -> Self {
|
||||||
|
CompilerError::HipError(error_code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<amd_comgr_status_s> for CompilerError {
|
||||||
|
fn from(error_code: amd_comgr_status_s) -> Self {
|
||||||
|
CompilerError::ComgrError(error_code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec<PtxError<'_>>> for CompilerError {
|
||||||
|
fn from(causes: Vec<PtxError>) -> Self {
|
||||||
|
let errors: Vec<String> = causes.iter().map(PtxError::to_string).collect();
|
||||||
|
let msg = errors.join("\n");
|
||||||
|
CompilerError::PtxParserError(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for CompilerError {
|
||||||
|
fn from(cause: io::Error) -> Self {
|
||||||
|
CompilerError::IoError(cause)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Utf8Error> for CompilerError {
|
||||||
|
fn from(cause: Utf8Error) -> Self {
|
||||||
|
CompilerError::ParseFileError(cause)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TranslateError> for CompilerError {
|
||||||
|
fn from(cause: TranslateError) -> Self {
|
||||||
|
CompilerError::PtxTranslateError(cause)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error;
|
|
||||||
use std::ffi::{CStr, OsStr};
|
use std::ffi::{CStr, OsStr};
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
@ -7,10 +6,11 @@ use std::mem::MaybeUninit;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::str::{self, FromStr};
|
use std::str::{self, FromStr};
|
||||||
|
|
||||||
use amd_comgr_sys::amd_comgr_status_s;
|
use amd_comgr_sys::amd_comgr_data_kind_s;
|
||||||
use bpaf::Bpaf;
|
use bpaf::Bpaf;
|
||||||
use hip_runtime_sys::hipErrorCode_t;
|
|
||||||
use ptx_parser::PtxError;
|
mod error;
|
||||||
|
use error::CompilerError;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Bpaf)]
|
#[derive(Debug, Clone, Bpaf)]
|
||||||
#[bpaf(options, version)]
|
#[bpaf(options, version)]
|
||||||
|
@ -23,13 +23,13 @@ pub struct Options {
|
||||||
ptx_path: String,
|
ptx_path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> 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();
|
||||||
|
|
||||||
match output_type {
|
match output_type {
|
||||||
OutputType::LlvmIrLinked | OutputType::Assembly => todo!(),
|
OutputType::Assembly => todo!(),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,24 +39,30 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let output_path = get_output_path(&ptx_path, &output_type)?;
|
let output_path = get_output_path(&ptx_path, &output_type)?;
|
||||||
check_path(&output_path)?;
|
check_path(&output_path)?;
|
||||||
|
|
||||||
let ptx = fs::read(&ptx_path)?;
|
let ptx = fs::read(&ptx_path).map_err(CompilerError::from)?;
|
||||||
let ptx = str::from_utf8(&ptx)?;
|
let ptx = str::from_utf8(&ptx).map_err(CompilerError::from)?;
|
||||||
let llvm = ptx_to_llvm(ptx)?;
|
let llvm = ptx_to_llvm(ptx).map_err(CompilerError::from)?;
|
||||||
|
|
||||||
if output_type == OutputType::LlvmIrPreLinked {
|
if output_type == OutputType::LlvmIrPreLinked {
|
||||||
write_to_file(&llvm.llvm_ir, &output_path)?;
|
write_to_file(&llvm.llvm_ir, &output_path).map_err(CompilerError::from)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if output_type == OutputType::LlvmIrLinked {
|
||||||
|
let linked_llvm = link_llvm(&llvm)?;
|
||||||
|
write_to_file(&linked_llvm, &output_path).map_err(CompilerError::from)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let elf = llvm_to_elf(&llvm)?;
|
let elf = llvm_to_elf(&llvm)?;
|
||||||
write_to_file(&elf, &output_path)?;
|
write_to_file(&elf, &output_path).map_err(CompilerError::from)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ptx_to_llvm(ptx: &str) -> Result<LLVMArtifacts, Box<dyn Error>> {
|
fn ptx_to_llvm(ptx: &str) -> Result<LLVMArtifacts, CompilerError> {
|
||||||
let ast = ptx_parser::parse_module_checked(ptx).map_err(join_ptx_errors)?;
|
let ast = ptx_parser::parse_module_checked(ptx).map_err(CompilerError::from).map_err(CompilerError::from)?;
|
||||||
let module = ptx::to_llvm_module(ast)?;
|
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();
|
||||||
let llvm_ir = module.llvm_ir.print_module_to_string().to_bytes().to_vec();
|
let llvm_ir = module.llvm_ir.print_module_to_string().to_bytes().to_vec();
|
||||||
|
@ -74,12 +80,14 @@ struct LLVMArtifacts {
|
||||||
llvm_ir: Vec<u8>,
|
llvm_ir: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn join_ptx_errors(vector: Vec<PtxError>) -> String {
|
fn link_llvm(llvm: &LLVMArtifacts) -> Result<Vec<u8>, CompilerError> {
|
||||||
let errors: Vec<String> = vector.iter().map(PtxError::to_string).collect();
|
let linked_bitcode = comgr::link_bitcode(&llvm.bitcode, &llvm.linked_bitcode)?;
|
||||||
errors.join("\n")
|
let data = linked_bitcode.get_data(amd_comgr_data_kind_s::AMD_COMGR_DATA_KIND_BC, 0)?;
|
||||||
|
let linked_llvm = data.copy_content().map_err(CompilerError::from)?;
|
||||||
|
Ok(ptx::bitcode_to_ir(linked_llvm))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn llvm_to_elf(llvm: &LLVMArtifacts) -> Result<Vec<u8>, ElfError> {
|
fn llvm_to_elf(llvm: &LLVMArtifacts) -> Result<Vec<u8>, CompilerError> {
|
||||||
use hip_runtime_sys::*;
|
use hip_runtime_sys::*;
|
||||||
unsafe { hipInit(0) }?;
|
unsafe { hipInit(0) }?;
|
||||||
let mut dev_props: MaybeUninit<hipDeviceProp_tR0600> = MaybeUninit::uninit();
|
let mut dev_props: MaybeUninit<hipDeviceProp_tR0600> = MaybeUninit::uninit();
|
||||||
|
@ -87,13 +95,12 @@ fn llvm_to_elf(llvm: &LLVMArtifacts) -> Result<Vec<u8>, ElfError> {
|
||||||
let dev_props = unsafe { dev_props.assume_init() };
|
let dev_props = unsafe { dev_props.assume_init() };
|
||||||
let gcn_arch = unsafe { CStr::from_ptr(dev_props.gcnArchName.as_ptr()) };
|
let gcn_arch = unsafe { CStr::from_ptr(dev_props.gcnArchName.as_ptr()) };
|
||||||
|
|
||||||
comgr::compile_bitcode(gcn_arch, &llvm.bitcode, &llvm.linked_bitcode).map_err(ElfError::from)
|
comgr::compile_bitcode(gcn_arch, &llvm.bitcode, &llvm.linked_bitcode).map_err(CompilerError::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_path(path: &Path) -> Result<(), Box<dyn Error>> {
|
fn check_path(path: &Path) -> Result<(), CompilerError> {
|
||||||
if path.try_exists()? && !path.is_file() {
|
if path.try_exists().map_err(CompilerError::from)? && !path.is_file() {
|
||||||
let error = CheckPathError(path.to_path_buf());
|
let error = CompilerError::CheckPathError(path.to_path_buf());
|
||||||
let error = Box::new(error);
|
|
||||||
return Err(error);
|
return Err(error);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -102,8 +109,8 @@ fn check_path(path: &Path) -> Result<(), Box<dyn Error>> {
|
||||||
fn get_output_path(
|
fn get_output_path(
|
||||||
ptx_path: &PathBuf,
|
ptx_path: &PathBuf,
|
||||||
output_type: &OutputType,
|
output_type: &OutputType,
|
||||||
) -> Result<PathBuf, Box<dyn Error>> {
|
) -> Result<PathBuf, CompilerError> {
|
||||||
let current_dir = env::current_dir()?;
|
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
|
||||||
.as_path()
|
.as_path()
|
||||||
|
@ -150,7 +157,7 @@ impl OutputType {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for OutputType {
|
impl FromStr for OutputType {
|
||||||
type Err = ParseOutputTypeError;
|
type Err = CompilerError;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
match s {
|
match s {
|
||||||
|
@ -158,35 +165,7 @@ 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(ParseOutputTypeError(s.into())),
|
_ => Err(CompilerError::ParseOutputTypeError(s.into())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
|
||||||
#[error("Not a regular file: {0}")]
|
|
||||||
struct CheckPathError(PathBuf);
|
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
|
||||||
#[error("Invalid output type: {0}")]
|
|
||||||
struct ParseOutputTypeError(String);
|
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
|
||||||
enum ElfError {
|
|
||||||
#[error("HIP error: {0:?}")]
|
|
||||||
HipError(hipErrorCode_t),
|
|
||||||
#[error("amd_comgr error: {0:?}")]
|
|
||||||
AmdComgrError(amd_comgr_status_s),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<hipErrorCode_t> for ElfError {
|
|
||||||
fn from(value: hipErrorCode_t) -> Self {
|
|
||||||
ElfError::HipError(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<amd_comgr_status_s> for ElfError {
|
|
||||||
fn from(value: amd_comgr_status_s) -> Self {
|
|
||||||
ElfError::AmdComgrError(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue