@@ -167,16 +167,16 @@ use rustc_session::Session;
167
167
use rustc_session:: config:: { self , OutputFilenames , OutputType } ;
168
168
use rustc_span:: symbol:: Symbol ;
169
169
use std:: any:: Any ;
170
- use std:: fs:: { File , create_dir_all } ;
170
+ use std:: fs;
171
171
use std:: io:: Cursor ;
172
172
use std:: io:: Write ;
173
173
use std:: path:: Path ;
174
174
use std:: sync:: Arc ;
175
175
use tracing:: { error, warn} ;
176
176
177
177
fn dump_mir ( tcx : TyCtxt < ' _ > , mono_items : & [ ( MonoItem < ' _ > , MonoItemData ) ] , path : & Path ) {
178
- create_dir_all ( path. parent ( ) . unwrap ( ) ) . unwrap ( ) ;
179
- let mut file = File :: create ( path) . unwrap ( ) ;
178
+ fs :: create_dir_all ( path. parent ( ) . unwrap ( ) ) . unwrap ( ) ;
179
+ let mut file = fs :: File :: create ( path) . unwrap ( ) ;
180
180
for & ( mono_item, _) in mono_items {
181
181
if let MonoItem :: Fn ( instance) = mono_item
182
182
&& matches ! ( instance. def, InstanceKind :: Item ( _) )
@@ -189,27 +189,6 @@ fn dump_mir(tcx: TyCtxt<'_>, mono_items: &[(MonoItem<'_>, MonoItemData)], path:
189
189
}
190
190
}
191
191
192
- // TODO: Should this store Vec or Module?
193
- struct SpirvModuleBuffer ( Vec < u32 > ) ;
194
-
195
- impl ModuleBufferMethods for SpirvModuleBuffer {
196
- fn data ( & self ) -> & [ u8 ] {
197
- spirv_tools:: binary:: from_binary ( & self . 0 )
198
- }
199
- }
200
-
201
- // TODO: Should this store Vec or Module?
202
- struct SpirvThinBuffer ( Vec < u32 > ) ;
203
-
204
- impl ThinBufferMethods for SpirvThinBuffer {
205
- fn data ( & self ) -> & [ u8 ] {
206
- spirv_tools:: binary:: from_binary ( & self . 0 )
207
- }
208
- fn thin_link_data ( & self ) -> & [ u8 ] {
209
- & [ ]
210
- }
211
- }
212
-
213
192
#[ derive( Clone ) ]
214
193
struct SpirvCodegenBackend ;
215
194
@@ -306,28 +285,76 @@ impl CodegenBackend for SpirvCodegenBackend {
306
285
}
307
286
}
308
287
288
+ struct SpirvModuleBuffer ( Vec < u32 > ) ;
289
+
290
+ impl SpirvModuleBuffer {
291
+ fn as_bytes ( & self ) -> & [ u8 ] {
292
+ spirv_tools:: binary:: from_binary ( & self . 0 )
293
+ }
294
+ }
295
+ impl ModuleBufferMethods for SpirvModuleBuffer {
296
+ fn data ( & self ) -> & [ u8 ] {
297
+ self . as_bytes ( )
298
+ }
299
+ }
300
+ impl ThinBufferMethods for SpirvModuleBuffer {
301
+ fn data ( & self ) -> & [ u8 ] {
302
+ self . as_bytes ( )
303
+ }
304
+ fn thin_link_data ( & self ) -> & [ u8 ] {
305
+ & [ ]
306
+ }
307
+ }
308
+
309
+ impl SpirvCodegenBackend {
310
+ fn optimize_common (
311
+ _cgcx : & CodegenContext < Self > ,
312
+ _module : & mut ModuleCodegen < <Self as WriteBackendMethods >:: Module > ,
313
+ ) -> Result < ( ) , FatalError > {
314
+ // FIXME(eddyb) actually run as many optimization passes as possible,
315
+ // before ever serializing `.spv` files that will later get linked.
316
+ Ok ( ( ) )
317
+ }
318
+ }
319
+
309
320
impl WriteBackendMethods for SpirvCodegenBackend {
310
- type Module = Vec < u32 > ;
321
+ type Module = rspirv :: dr :: Module ;
311
322
type TargetMachine = ( ) ;
312
323
type TargetMachineError = String ;
313
324
type ModuleBuffer = SpirvModuleBuffer ;
314
325
type ThinData = ( ) ;
315
- type ThinBuffer = SpirvThinBuffer ;
326
+ type ThinBuffer = SpirvModuleBuffer ;
316
327
328
+ // FIXME(eddyb) reuse the "merge" stage of `crate::linker` for this, or even
329
+ // delegate to `run_fat_lto` (although `-Zcombine-cgu` is much more niche).
317
330
fn run_link (
318
- _cgcx : & CodegenContext < Self > ,
319
- _diag_handler : DiagCtxtHandle < ' _ > ,
331
+ cgcx : & CodegenContext < Self > ,
332
+ diag_handler : DiagCtxtHandle < ' _ > ,
320
333
_modules : Vec < ModuleCodegen < Self :: Module > > ,
321
334
) -> Result < ModuleCodegen < Self :: Module > , FatalError > {
322
- todo ! ( )
335
+ assert ! (
336
+ cgcx. opts. unstable_opts. combine_cgu,
337
+ "`run_link` (for `WorkItemResult::NeedsLink`) should \
338
+ only be invoked due to `-Zcombine-cgu`"
339
+ ) ;
340
+ diag_handler. fatal ( "Rust-GPU does not support `-Zcombine-cgu`" )
323
341
}
324
342
343
+ // FIXME(eddyb) reuse the "merge" stage of `crate::linker` for this, or even
344
+ // consider setting `requires_lto = true` in the target specs and moving the
345
+ // entirety of `crate::linker` into this stage (lacking diagnostics may be
346
+ // an issue - it's surprising `CodegenBackend::link` has `Session` at all).
325
347
fn run_fat_lto (
326
- _ : & CodegenContext < Self > ,
327
- _ : Vec < FatLtoInput < Self > > ,
328
- _ : Vec < ( SerializedModule < Self :: ModuleBuffer > , WorkProduct ) > ,
348
+ cgcx : & CodegenContext < Self > ,
349
+ _modules : Vec < FatLtoInput < Self > > ,
350
+ _cached_modules : Vec < ( SerializedModule < Self :: ModuleBuffer > , WorkProduct ) > ,
329
351
) -> Result < LtoModuleCodegen < Self > , FatalError > {
330
- todo ! ( )
352
+ assert ! (
353
+ cgcx. lto == rustc_session:: config:: Lto :: Fat ,
354
+ "`run_fat_lto` (for `WorkItemResult::NeedsFatLto`) should \
355
+ only be invoked due to `-Clto` (or equivalent)"
356
+ ) ;
357
+ unreachable ! ( "Rust-GPU does not support fat LTO" )
331
358
}
332
359
333
360
fn run_thin_lto (
@@ -347,35 +374,39 @@ impl WriteBackendMethods for SpirvCodegenBackend {
347
374
}
348
375
349
376
fn optimize (
350
- _ : & CodegenContext < Self > ,
351
- _ : DiagCtxtHandle < ' _ > ,
352
- _ : & mut ModuleCodegen < Self :: Module > ,
353
- _ : & ModuleConfig ,
377
+ cgcx : & CodegenContext < Self > ,
378
+ _dcx : DiagCtxtHandle < ' _ > ,
379
+ module : & mut ModuleCodegen < Self :: Module > ,
380
+ _config : & ModuleConfig ,
354
381
) -> Result < ( ) , FatalError > {
355
- // TODO: Implement
356
- Ok ( ( ) )
382
+ Self :: optimize_common ( cgcx, module)
357
383
}
358
384
359
385
fn optimize_thin (
360
- _cgcx : & CodegenContext < Self > ,
386
+ cgcx : & CodegenContext < Self > ,
361
387
thin_module : ThinModule < Self > ,
362
388
) -> Result < ModuleCodegen < Self :: Module > , FatalError > {
363
- let module = ModuleCodegen {
364
- module_llvm : spirv_tools:: binary:: to_binary ( thin_module. data ( ) )
365
- . unwrap ( )
366
- . to_vec ( ) ,
389
+ // FIXME(eddyb) the inefficiency of Module -> [u8] -> Module roundtrips
390
+ // comes from upstream and it applies to `rustc_codegen_llvm` as well,
391
+ // eventually it should be properly addressed (for `ThinLocal` at least).
392
+ let mut module = ModuleCodegen {
393
+ module_llvm : link:: with_rspirv_loader ( |loader| {
394
+ rspirv:: binary:: parse_bytes ( thin_module. data ( ) , loader)
395
+ } )
396
+ . unwrap ( ) ,
367
397
name : thin_module. name ( ) . to_string ( ) ,
368
398
kind : ModuleKind :: Regular ,
369
399
thin_lto_buffer : None ,
370
400
} ;
401
+ Self :: optimize_common ( cgcx, & mut module) ?;
371
402
Ok ( module)
372
403
}
373
404
374
405
fn optimize_fat (
375
- _ : & CodegenContext < Self > ,
376
- _ : & mut ModuleCodegen < Self :: Module > ,
406
+ cgcx : & CodegenContext < Self > ,
407
+ module : & mut ModuleCodegen < Self :: Module > ,
377
408
) -> Result < ( ) , FatalError > {
378
- todo ! ( )
409
+ Self :: optimize_common ( cgcx , module )
379
410
}
380
411
381
412
fn codegen (
@@ -384,20 +415,19 @@ impl WriteBackendMethods for SpirvCodegenBackend {
384
415
module : ModuleCodegen < Self :: Module > ,
385
416
_config : & ModuleConfig ,
386
417
) -> Result < CompiledModule , FatalError > {
418
+ let kind = module. kind ;
419
+ let ( name, module_buffer) = Self :: serialize_module ( module) ;
420
+
387
421
let path = cgcx. output_filenames . temp_path_for_cgu (
388
422
OutputType :: Object ,
389
- & module . name ,
423
+ & name,
390
424
cgcx. invocation_temp . as_deref ( ) ,
391
425
) ;
392
- // Note: endianness doesn't matter, readers deduce endianness from magic header.
393
- let spirv_module = spirv_tools:: binary:: from_binary ( & module. module_llvm ) ;
394
- File :: create ( & path)
395
- . unwrap ( )
396
- . write_all ( spirv_module)
397
- . unwrap ( ) ;
426
+ fs:: write ( & path, module_buffer. as_bytes ( ) ) . unwrap ( ) ;
427
+
398
428
Ok ( CompiledModule {
399
- name : module . name ,
400
- kind : module . kind ,
429
+ name,
430
+ kind,
401
431
object : Some ( path) ,
402
432
dwarf_object : None ,
403
433
bytecode : None ,
@@ -411,11 +441,14 @@ impl WriteBackendMethods for SpirvCodegenBackend {
411
441
module : ModuleCodegen < Self :: Module > ,
412
442
_want_summary : bool ,
413
443
) -> ( String , Self :: ThinBuffer ) {
414
- ( module. name , SpirvThinBuffer ( module . module_llvm ) )
444
+ Self :: serialize_module ( module)
415
445
}
416
446
417
447
fn serialize_module ( module : ModuleCodegen < Self :: Module > ) -> ( String , Self :: ModuleBuffer ) {
418
- ( module. name , SpirvModuleBuffer ( module. module_llvm ) )
448
+ (
449
+ module. name ,
450
+ SpirvModuleBuffer ( module. module_llvm . assemble ( ) ) ,
451
+ )
419
452
}
420
453
421
454
fn autodiff (
@@ -424,7 +457,7 @@ impl WriteBackendMethods for SpirvCodegenBackend {
424
457
_diff_fncs : Vec < AutoDiffItem > ,
425
458
_config : & ModuleConfig ,
426
459
) -> Result < ( ) , FatalError > {
427
- todo ! ( )
460
+ unreachable ! ( "Rust-GPU does not support autodiff" )
428
461
}
429
462
}
430
463
@@ -490,12 +523,11 @@ impl ExtraBackendMethods for SpirvCodegenBackend {
490
523
} else {
491
524
with_no_trimmed_paths ! ( do_codegen( & mut cx) ) ;
492
525
}
493
- let spirv_module = cx. finalize_module ( ) . assemble ( ) ;
494
526
495
527
(
496
528
ModuleCodegen {
497
529
name : cgu_name. to_string ( ) ,
498
- module_llvm : spirv_module ,
530
+ module_llvm : cx . finalize_module ( ) ,
499
531
kind : ModuleKind :: Regular ,
500
532
thin_lto_buffer : None ,
501
533
} ,
0 commit comments