1pub use cubecl_runtime::kernel::*;
5
6use alloc::string::{String, ToString};
7use core::{
8 fmt::Display,
9 sync::atomic::{AtomicI8, Ordering},
10};
11
12use cubecl_common::format::format_str;
13use cubecl_environment::backtrace::BackTrace;
14
15use crate::{
16 compiler::{CompilationError, CompilationRecording, Compiler},
17 config::{CubeClRuntimeConfig, RuntimeConfig, compilation::CompilationLogLevel},
18 id::KernelId,
19 server::CubeDim,
20};
21
22pub struct CompiledKernel<C: Compiler> {
24 pub entrypoint_name: String,
34
35 pub debug_name: Option<&'static str>,
53
54 pub source: String,
56 pub repr: Option<C::Representation>,
58 pub cube_dim: CubeDim,
60 pub io: Option<alloc::vec::Vec<BufferIOAttr>>,
66 pub debug_info: Option<DebugInformation>,
68}
69
70#[derive(new)]
72pub struct DebugInformation {
73 pub lang_tag: &'static str,
75 pub id: KernelId,
77}
78
79impl<C: Compiler> CompiledKernel<C> {
80 pub fn lower(
84 kernel: &dyn CubeKernel,
85 recording: &mut CompilationRecording,
86 compile: impl FnOnce(KernelDefinition) -> Result<Self, CompilationError>,
87 ) -> Result<Self, CompilationError> {
88 let definition = define_kernel(kernel)?;
89 recording.defined(&definition);
90 let compiled = compile(definition)?;
91 recording.source(&compiled.source);
92 Ok(compiled)
93 }
94
95 pub fn compile(
98 kernel: &dyn CubeKernel,
99 definition: KernelDefinition,
100 compiler: &mut C,
101 compilation_options: &C::CompilationOptions,
102 ) -> Result<Self, CompilationError> {
103 let entrypoint_name = definition.settings.kernel_name.clone();
104 let cube_dim = definition.settings.cube_dim.into();
105
106 if let Some(precompiled) = kernel.source() {
111 if precompiled.lang != compiler.lang_tag() {
112 return Err(CompilationError::Generic {
113 reason: alloc::format!(
114 "kernel `{}` carries {} source, but this compiler expects {}",
115 kernel.name(),
116 precompiled.lang,
117 compiler.lang_tag()
118 ),
119 backtrace: BackTrace::capture(),
120 });
121 }
122 return Ok(CompiledKernel {
123 entrypoint_name: precompiled.entrypoint_name,
124 debug_name: Some(kernel.name()),
125 source: precompiled.source,
126 io: None,
127 repr: None,
128 cube_dim,
129 debug_info: None,
130 });
131 }
132
133 let lower_level_ir = compiler.compile(definition, compilation_options)?;
134
135 Ok(CompiledKernel {
136 entrypoint_name,
137 debug_name: Some(kernel.name()),
138 source: lower_level_ir.to_string(),
139 io: C::buffer_io(&lower_level_ir),
140 repr: Some(lower_level_ir),
141 cube_dim,
142 debug_info: None,
143 })
144 }
145}
146
147static COMPILATION_LEVEL: AtomicI8 = AtomicI8::new(-1);
148
149fn compilation_level() -> u8 {
150 let compilation_level = COMPILATION_LEVEL.load(Ordering::Relaxed);
151 if compilation_level == -1 {
152 let val = match CubeClRuntimeConfig::get().compilation.logger.level {
153 CompilationLogLevel::Full => 2,
154 CompilationLogLevel::Disabled => 0,
155 CompilationLogLevel::Basic => 1,
156 };
157
158 COMPILATION_LEVEL.store(val, Ordering::Relaxed);
159 val as u8
160 } else {
161 compilation_level as u8
162 }
163}
164
165impl<C: Compiler> Display for CompiledKernel<C> {
166 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
167 match compilation_level() {
168 2 => self.format_full(f),
169 _ => self.format_basic(f),
170 }
171 }
172}
173
174impl<C: Compiler> CompiledKernel<C> {
175 fn format_basic(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
176 f.write_str("[Compiling kernel]")?;
177 if let Some(name) = self.debug_name {
178 if name.len() <= 32 {
179 f.write_fmt(format_args!(" {name}"))?;
180 } else {
181 f.write_fmt(format_args!(" {}", name.split('<').next().unwrap_or("")))?;
182 }
183 }
184
185 Ok(())
186 }
187
188 fn format_full(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
189 f.write_str("[START_KERNEL_COMPILATION]")?;
190
191 if let Some(name) = self.debug_name {
192 if name.len() <= 32 {
193 f.write_fmt(format_args!("\nname: {name}"))?;
194 } else {
195 let name = format_str(name, &[('<', '>')], false);
196 f.write_fmt(format_args!("\nname: {name}"))?;
197 }
198 }
199
200 if let Some(info) = &self.debug_info {
201 f.write_fmt(format_args!("\nid: {:#?}", info.id))?;
202 }
203
204 f.write_fmt(format_args!(
205 "
206source:
207```{}
208{}
209```
210[END_KERNEL_COMPILATION]
211",
212 self.debug_info
213 .as_ref()
214 .map(|info| info.lang_tag)
215 .unwrap_or(""),
216 self.source
217 ))
218 }
219}