diff --git a/toolchain/check/cpp/export.cpp b/toolchain/check/cpp/export.cpp index 7813e6037957..75764ff508e3 100644 --- a/toolchain/check/cpp/export.cpp +++ b/toolchain/check/cpp/export.cpp @@ -1144,14 +1144,8 @@ auto ExportFunctionSpecializationToCpp( auto bindings = context.inst_blocks().Get(generic.bindings_id); CARBON_CHECK(bindings.size() == template_args.size()); - // This name will be appended to the thunk name to disambiguate - // between specializations. - std::string extra_name; - // Map the `clang::TemplateArgument`s into Carbon types suitable for // passing into `MakeSpecific`. - // - // Also initialize `extra_name`. llvm::SmallVector specific_arg_ids; for (auto [binding_inst_id, clang_template_arg] : llvm::zip(bindings, template_args)) { @@ -1165,9 +1159,6 @@ auto ExportFunctionSpecializationToCpp( return false; } - // TODO: this generates a pretty ugly name. - extra_name += std::string(llvm::formatv("{}", type_expr.inst_id)); - auto binding_const_inst_id = context.constant_values().GetConstantInstId(binding_inst_id); @@ -1180,6 +1171,11 @@ auto ExportFunctionSpecializationToCpp( // parameters with symbolic types to concrete types. auto specific_id = MakeSpecific(context, loc_id, target.function.generic_id, specific_arg_ids); + // This name is appended to the thunk name to disambiguate between + // specializations. + SemIR::Mangler m(context.sem_ir(), context.total_ir_count(), + context.mangle_string_fingerprint()); + auto extra_name = m.MangleSpecificId(specific_id); target.return_type_id = target.function.GetDeclaredReturnType(context.sem_ir(), specific_id); for (auto& param : target.explicit_params) { diff --git a/toolchain/check/testdata/interop/cpp/function/export/generic.carbon b/toolchain/check/testdata/interop/cpp/function/export/generic.carbon index fc793f4e5349..a14042e95617 100644 --- a/toolchain/check/testdata/interop/cpp/function/export/generic.carbon +++ b/toolchain/check/testdata/interop/cpp/function/export/generic.carbon @@ -486,14 +486,14 @@ void G() { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F__carbon_thunkinst64000043(%_.param.loc24_23.1: ref %A, %_.param.loc24_23.2: ref %A) { +// CHECK:STDOUT: fn @F__carbon_thunk.83afdff581006d1a(%_.param.loc24_23.1: ref %A, %_.param.loc24_23.2: ref %A) { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %F__carbon_thunkinst64000043.ref: %F.type = name_ref F__carbon_thunkinst64000043, file.%F.decl [concrete = constants.%F] +// CHECK:STDOUT: %F__carbon_thunk.83afdff581006d1a.ref: %F.type = name_ref F__carbon_thunk.83afdff581006d1a, file.%F.decl [concrete = constants.%F] // CHECK:STDOUT: %I.facet.loc24_23.1: %I.type = facet_value constants.%A, (constants.%I.impl_witness.6ad) [concrete = constants.%I.facet.64b] // CHECK:STDOUT: %.loc24_23.1: %I.type = converted constants.%A, %I.facet.loc24_23.1 [concrete = constants.%I.facet.64b] // CHECK:STDOUT: %I.facet.loc24_23.2: %I.type = facet_value constants.%A, (constants.%I.impl_witness.6ad) [concrete = constants.%I.facet.64b] // CHECK:STDOUT: %.loc24_23.2: %I.type = converted constants.%A, %I.facet.loc24_23.2 [concrete = constants.%I.facet.64b] -// CHECK:STDOUT: %F.specific_fn: = specific_function %F__carbon_thunkinst64000043.ref, @F(constants.%I.facet.64b) [concrete = constants.%F.specific_fn.f33] +// CHECK:STDOUT: %F.specific_fn: = specific_function %F__carbon_thunk.83afdff581006d1a.ref, @F(constants.%I.facet.64b) [concrete = constants.%F.specific_fn.f33] // CHECK:STDOUT: %.loc24_23.3: ref %A = splice_block %_.param.loc24_23.2 {} // CHECK:STDOUT: %.loc24_23.4: %A = acquire_value %_.param.loc24_23.1 // CHECK:STDOUT: %F.call: init %A to %.loc24_23.3 = call %F.specific_fn(%.loc24_23.4) @@ -501,14 +501,14 @@ void G() { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F__carbon_thunkinst6400006E(%_.param.loc24_23.1: ref %B, %_.param.loc24_23.2: ref %B) { +// CHECK:STDOUT: fn @F__carbon_thunk.36f470e96b413347(%_.param.loc24_23.1: ref %B, %_.param.loc24_23.2: ref %B) { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %F__carbon_thunkinst6400006E.ref: %F.type = name_ref F__carbon_thunkinst6400006E, file.%F.decl [concrete = constants.%F] +// CHECK:STDOUT: %F__carbon_thunk.36f470e96b413347.ref: %F.type = name_ref F__carbon_thunk.36f470e96b413347, file.%F.decl [concrete = constants.%F] // CHECK:STDOUT: %I.facet.loc24_23.1: %I.type = facet_value constants.%B, (constants.%I.impl_witness.5b8) [concrete = constants.%I.facet.9f8] // CHECK:STDOUT: %.loc24_23.1: %I.type = converted constants.%B, %I.facet.loc24_23.1 [concrete = constants.%I.facet.9f8] // CHECK:STDOUT: %I.facet.loc24_23.2: %I.type = facet_value constants.%B, (constants.%I.impl_witness.5b8) [concrete = constants.%I.facet.9f8] // CHECK:STDOUT: %.loc24_23.2: %I.type = converted constants.%B, %I.facet.loc24_23.2 [concrete = constants.%I.facet.9f8] -// CHECK:STDOUT: %F.specific_fn: = specific_function %F__carbon_thunkinst6400006E.ref, @F(constants.%I.facet.9f8) [concrete = constants.%F.specific_fn.db2] +// CHECK:STDOUT: %F.specific_fn: = specific_function %F__carbon_thunk.36f470e96b413347.ref, @F(constants.%I.facet.9f8) [concrete = constants.%F.specific_fn.db2] // CHECK:STDOUT: %.loc24_23.3: ref %B = splice_block %_.param.loc24_23.2 {} // CHECK:STDOUT: %.loc24_23.4: %B = acquire_value %_.param.loc24_23.1 // CHECK:STDOUT: %F.call: init %B to %.loc24_23.3 = call %F.specific_fn(%.loc24_23.4) diff --git a/toolchain/lower/testdata/interop/cpp/function/export/generic.carbon b/toolchain/lower/testdata/interop/cpp/function/export/generic.carbon index a7aca55cfcb7..f0bd2f44e78d 100644 --- a/toolchain/lower/testdata/interop/cpp/function/export/generic.carbon +++ b/toolchain/lower/testdata/interop/cpp/function/export/generic.carbon @@ -132,7 +132,7 @@ fn Run() { // CHECK:STDOUT: define internal void @_ZN6CarbonL1FENS_1AE() #2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %0 = alloca %"class.Carbon::A", align 1 -// CHECK:STDOUT: call void @_CF__carbon_thunkinst70000035.Main(ptr noundef nonnull align 1 %0) +// CHECK:STDOUT: call void @_CF__carbon_thunk.83afdff581006d1a.Main(ptr noundef nonnull align 1 %0) // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: @@ -152,7 +152,7 @@ fn Run() { // CHECK:STDOUT: define internal void @_ZN6CarbonL1FENS_1BE() #2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %0 = alloca %"class.Carbon::B", align 1 -// CHECK:STDOUT: call void @_CF__carbon_thunkinst70000052.Main(ptr noundef nonnull align 1 %0) +// CHECK:STDOUT: call void @_CF__carbon_thunk.36f470e96b413347.Main(ptr noundef nonnull align 1 %0) // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: @@ -208,14 +208,14 @@ fn Run() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define void @_CF__carbon_thunkinst70000035.Main(ptr %_) #4 !dbg !44 { +// CHECK:STDOUT: define void @_CF__carbon_thunk.83afdff581006d1a.Main(ptr %_) #4 !dbg !44 { // CHECK:STDOUT: entry: // CHECK:STDOUT: call void @_CF.Main.3e1f7ed08cd9ee58(ptr %_), !dbg !47 // CHECK:STDOUT: ret void, !dbg !47 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define void @_CF__carbon_thunkinst70000052.Main(ptr %_) #4 !dbg !48 { +// CHECK:STDOUT: define void @_CF__carbon_thunk.36f470e96b413347.Main(ptr %_) #4 !dbg !48 { // CHECK:STDOUT: entry: // CHECK:STDOUT: call void @_CF.Main.bd1b6d59f703c190(ptr %_), !dbg !51 // CHECK:STDOUT: ret void, !dbg !51 @@ -303,11 +303,11 @@ fn Run() { // CHECK:STDOUT: !41 = !{!42} // CHECK:STDOUT: !42 = !DILocalVariable(arg: 1, scope: !40, type: !20) // CHECK:STDOUT: !43 = !DILocation(line: 13, column: 1, scope: !40) -// CHECK:STDOUT: !44 = distinct !DISubprogram(name: "F__carbon_thunkinst70000035", linkageName: "_CF__carbon_thunkinst70000035.Main", scope: null, file: !1, line: 19, type: !18, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !45) +// CHECK:STDOUT: !44 = distinct !DISubprogram(name: "F__carbon_thunk.83afdff581006d1a", linkageName: "_CF__carbon_thunk.83afdff581006d1a.Main", scope: null, file: !1, line: 19, type: !18, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !45) // CHECK:STDOUT: !45 = !{!46} // CHECK:STDOUT: !46 = !DILocalVariable(arg: 1, scope: !44, type: !20) // CHECK:STDOUT: !47 = !DILocation(line: 19, column: 1, scope: !44) -// CHECK:STDOUT: !48 = distinct !DISubprogram(name: "F__carbon_thunkinst70000052", linkageName: "_CF__carbon_thunkinst70000052.Main", scope: null, file: !1, line: 19, type: !18, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !49) +// CHECK:STDOUT: !48 = distinct !DISubprogram(name: "F__carbon_thunk.36f470e96b413347", linkageName: "_CF__carbon_thunk.36f470e96b413347.Main", scope: null, file: !1, line: 19, type: !18, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !49) // CHECK:STDOUT: !49 = !{!50} // CHECK:STDOUT: !50 = !DILocalVariable(arg: 1, scope: !48, type: !20) // CHECK:STDOUT: !51 = !DILocation(line: 19, column: 1, scope: !48) diff --git a/toolchain/sem_ir/mangler.cpp b/toolchain/sem_ir/mangler.cpp index d47f641c5770..e342b736d6d8 100644 --- a/toolchain/sem_ir/mangler.cpp +++ b/toolchain/sem_ir/mangler.cpp @@ -344,6 +344,12 @@ auto Mangler::MangleVTable(const SemIR::Class& class_info, return os.TakeStr(); } +auto Mangler::MangleSpecificId(SemIR::SpecificId specific_id) -> std::string { + RawStringOstream os; + MangleSpecificId(os, specific_id); + return os.TakeStr(); +} + auto Mangler::MangleUnqualifiedName(llvm::raw_ostream& os, const SemIR::EntityWithParamsBase& entity, SemIR::SpecificId specific_id) -> void { diff --git a/toolchain/sem_ir/mangler.h b/toolchain/sem_ir/mangler.h index ec7523942dec..99a036a442ee 100644 --- a/toolchain/sem_ir/mangler.h +++ b/toolchain/sem_ir/mangler.h @@ -49,6 +49,9 @@ class Mangler { auto MangleVTable(const SemIR::Class& class_info, SemIR::SpecificId specific_id) -> std::string; + // Produce a deterministically unique mangled name for a specific. + auto MangleSpecificId(SemIR::SpecificId specific_id) -> std::string; + private: auto MangleImpl(SemIR::FunctionId function_id, SemIR::SpecificId specific_id, llvm::raw_ostream& os) -> void;