1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use spirv_tools_sys::{assembler, shared};
pub struct CompiledAssembler {
inner: *mut shared::ToolContext,
}
use super::Assembler;
impl Assembler for CompiledAssembler {
fn with_env(target_env: crate::TargetEnv) -> Self {
Self {
inner: unsafe { shared::context_create(target_env) },
}
}
fn assemble(
&self,
text: &str,
options: super::AssemblerOptions,
) -> Result<crate::binary::Binary, crate::error::Error> {
unsafe {
let mut binary = std::ptr::null_mut();
let mut diagnostic = std::ptr::null_mut();
let res = assembler::assemble(
self.inner,
text.as_ptr().cast(),
text.len(),
options.into(),
&mut binary,
&mut diagnostic,
);
let diagnostic = crate::error::Diagnostic::from_diag(diagnostic).ok();
match res {
shared::SpirvResult::Success => {
if binary.is_null() {
return Err(crate::error::Error {
inner: shared::SpirvResult::InternalError,
diagnostic: Some("spirv assemble indicated success but did not return a valid binary".to_owned().into()),
});
}
let bin = crate::binary::external::ExternalBinary::new(binary);
Ok(crate::binary::Binary::External(bin))
}
other => Err(crate::error::Error {
inner: other,
diagnostic,
}),
}
}
}
fn disassemble(
&self,
binary: impl AsRef<[u32]>,
options: super::DisassembleOptions,
) -> Result<Option<String>, crate::error::Error> {
unsafe {
let mut text = std::ptr::null_mut();
let mut diagnostic = std::ptr::null_mut();
let binary = binary.as_ref();
let res = assembler::disassemble(
self.inner,
binary.as_ptr().cast(),
binary.len(),
options.into(),
&mut text,
&mut diagnostic,
);
let diagnostic = crate::error::Diagnostic::from_diag(diagnostic).ok();
match res {
shared::SpirvResult::Success => {
if text.is_null() {
return Ok(None);
}
let disassemble_res = std::str::from_utf8(std::slice::from_raw_parts(
(*text).data.cast::<u8>(),
(*text).length,
))
.map(|disasm| Some(disasm.to_owned()))
.map_err(|e| crate::error::Error {
inner: shared::SpirvResult::InvalidText,
diagnostic: Some(
format!("spirv disassemble returned non-utf8 text: {}", e).into(),
),
});
assembler::text_destroy(text);
disassemble_res
}
other => Err(crate::error::Error {
inner: other,
diagnostic,
}),
}
}
}
}
impl Default for CompiledAssembler {
fn default() -> Self {
Self::with_env(crate::TargetEnv::default())
}
}
impl Drop for CompiledAssembler {
fn drop(&mut self) {
unsafe {
shared::context_destroy(self.inner);
}
}
}