diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs index 292a5e26e1..1aaf294a07 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs @@ -515,6 +515,7 @@ impl CodegenArgs { // FIXME(eddyb) deduplicate between `CodegenArgs` and `linker::Options`. emit_multiple_modules: module_output_type == ModuleOutputType::Multiple, spirv_metadata, + keep_link_exports: false, // NOTE(eddyb) these are debugging options that used to be env vars // (for more information see `docs/src/codegen-args.md`). diff --git a/crates/rustc_codegen_spirv/src/linker/import_export_link.rs b/crates/rustc_codegen_spirv/src/linker/import_export_link.rs index 36e52f0061..dd6a1b88c9 100644 --- a/crates/rustc_codegen_spirv/src/linker/import_export_link.rs +++ b/crates/rustc_codegen_spirv/src/linker/import_export_link.rs @@ -5,10 +5,10 @@ use rspirv::spirv::{Capability, Decoration, LinkageType, Op, Word}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_session::Session; -pub fn run(sess: &Session, module: &mut Module) -> Result<()> { +pub fn run(opts: &super::Options, sess: &Session, module: &mut Module) -> Result<()> { let (rewrite_rules, killed_parameters) = find_import_export_pairs_and_killed_params(sess, module)?; - kill_linkage_instructions(module, &rewrite_rules); + kill_linkage_instructions(opts, module, &rewrite_rules); import_kill_annotations_and_debug(module, &rewrite_rules, &killed_parameters); replace_all_uses_with(module, &rewrite_rules); Ok(()) @@ -215,7 +215,11 @@ fn replace_all_uses_with(module: &mut Module, rules: &FxHashMap) { }); } -fn kill_linkage_instructions(module: &mut Module, rewrite_rules: &FxHashMap) { +fn kill_linkage_instructions( + opts: &super::Options, + module: &mut Module, + rewrite_rules: &FxHashMap, +) { // drop imported functions module .functions @@ -227,16 +231,27 @@ fn kill_linkage_instructions(module: &mut Module, rewrite_rules: &FxHashMap { + kept_any_linkage_decorations = true; + false + } + _ => true, + }) }); + if !kept_any_linkage_decorations { + // drop OpCapability Linkage + module.capabilities.retain(|inst| { + inst.class.opcode != Op::Capability + || inst.operands[0].unwrap_capability() != Capability::Linkage + }); + } } fn import_kill_annotations_and_debug( diff --git a/crates/rustc_codegen_spirv/src/linker/mod.rs b/crates/rustc_codegen_spirv/src/linker/mod.rs index 25876347d6..af44ce87d0 100644 --- a/crates/rustc_codegen_spirv/src/linker/mod.rs +++ b/crates/rustc_codegen_spirv/src/linker/mod.rs @@ -38,6 +38,12 @@ pub struct Options { pub emit_multiple_modules: bool, pub spirv_metadata: SpirvMetadata, + /// Whether to preserve `LinkageAttributes "..." Export` decorations, + /// even after resolving imports to exports. + /// + /// **Note**: currently only used for unit testing, and not exposed elsewhere. + pub keep_link_exports: bool, + // NOTE(eddyb) these are debugging options that used to be env vars // (for more information see `docs/src/codegen-args.md`). pub dump_post_merge: Option, @@ -176,7 +182,7 @@ pub fn link(sess: &Session, mut inputs: Vec, opts: &Options) -> Result Result { modules, &Options { compact_ids: true, + keep_link_exports: true, ..Default::default() }, ); @@ -194,11 +195,13 @@ fn standard() { ); let result = assemble_and_link(&[&a, &b]).unwrap(); - let expect = r#"OpMemoryModel Logical OpenCL - %1 = OpTypeFloat 32 - %2 = OpVariable %1 Input - %3 = OpConstant %1 42.0 - %4 = OpVariable %1 Uniform %3"#; + let expect = r#"OpCapability Linkage + OpMemoryModel Logical OpenCL + OpDecorate %1 LinkageAttributes "foo" Export + %2 = OpTypeFloat 32 + %3 = OpVariable %2 Input + %4 = OpConstant %2 42.0 + %1 = OpVariable %2 Uniform %4"#; without_header_eq(result, expect); } @@ -214,9 +217,11 @@ fn not_a_lib_extra_exports() { ); let result = assemble_and_link(&[&a]).unwrap(); - let expect = r#"OpMemoryModel Logical OpenCL - %1 = OpTypeFloat 32 - %2 = OpVariable %1 Uniform"#; + let expect = r#"OpCapability Linkage + OpMemoryModel Logical OpenCL + OpDecorate %1 LinkageAttributes "foo" Export + %2 = OpTypeFloat 32 + %1 = OpVariable %2 Uniform"#; without_header_eq(result, expect); } @@ -403,12 +408,14 @@ fn func_ctrl() { let result = assemble_and_link(&[&a, &b]).unwrap(); - let expect = r#"OpMemoryModel Logical OpenCL - %1 = OpTypeVoid - %2 = OpTypeFunction %1 - %3 = OpTypeFloat 32 - %4 = OpVariable %3 Uniform - %5 = OpFunction %1 DontInline %2 + let expect = r#"OpCapability Linkage + OpMemoryModel Logical OpenCL + OpDecorate %1 LinkageAttributes "foo" Export + %2 = OpTypeVoid + %3 = OpTypeFunction %2 + %4 = OpTypeFloat 32 + %5 = OpVariable %4 Uniform + %1 = OpFunction %2 DontInline %3 %6 = OpLabel OpReturn OpFunctionEnd"#; @@ -461,22 +468,24 @@ fn use_exported_func_param_attr() { let result = assemble_and_link(&[&a, &b]).unwrap(); let expect = r#"OpCapability Kernel + OpCapability Linkage OpMemoryModel Logical OpenCL OpDecorate %1 FuncParamAttr Zext - OpDecorate %2 FuncParamAttr Sext - %3 = OpTypeVoid - %4 = OpTypeInt 32 0 - %5 = OpTypeFunction %3 %4 - %6 = OpFunction %3 None %5 - %1 = OpFunctionParameter %4 - %7 = OpLabel - %8 = OpLoad %4 %1 + OpDecorate %2 LinkageAttributes "foo" Export + OpDecorate %3 FuncParamAttr Sext + %4 = OpTypeVoid + %5 = OpTypeInt 32 0 + %6 = OpTypeFunction %4 %5 + %7 = OpFunction %4 None %6 + %1 = OpFunctionParameter %5 + %8 = OpLabel + %9 = OpLoad %5 %1 OpReturn OpFunctionEnd - %9 = OpFunction %3 None %5 - %2 = OpFunctionParameter %4 + %2 = OpFunction %4 None %6 + %3 = OpFunctionParameter %5 %10 = OpLabel - %11 = OpLoad %4 %2 + %11 = OpLoad %5 %3 OpReturn OpFunctionEnd"#; @@ -535,11 +544,13 @@ fn names_and_decorations() { let result = assemble_and_link(&[&a, &b]).unwrap(); let expect = r#"OpCapability Kernel + OpCapability Linkage OpMemoryModel Logical OpenCL OpName %1 "foo" OpName %2 "param" OpDecorate %3 Restrict OpDecorate %3 NonWritable + OpDecorate %1 LinkageAttributes "foo" Export OpDecorate %2 Restrict %4 = OpTypeVoid %5 = OpTypeInt 32 0