Bläddra i källkod

Fix name mangling for Carbon functions called from C++ (#6984)

Since this requires using the `Mangler` class from `toolchain/check`,
moved it from `toolchain/lower` to `toolchain/sem_ir`.

The mangled name is then attached to the `FunctionDecl` with an
`AsmLabelAttr`.
Nicholas Bishop 1 månad sedan
förälder
incheckning
1ef35e8299

+ 1 - 0
toolchain/check/BUILD

@@ -183,6 +183,7 @@ cc_library(
         "//toolchain/sem_ir:expr_info",
         "//toolchain/sem_ir:file",
         "//toolchain/sem_ir:formatter",
+        "//toolchain/sem_ir:mangler",
         "//toolchain/sem_ir:typed_insts",
         "@llvm-project//clang:ast",
         "@llvm-project//clang:basic",

+ 1 - 0
toolchain/check/context.h

@@ -378,6 +378,7 @@ class Context {
     return sem_ir().inst_blocks();
   }
   auto constants() -> SemIR::ConstantStore& { return sem_ir().constants(); }
+  auto total_ir_count() const -> int { return total_ir_count_; }
 
   // --------------------------------------------------------------------------
   // End of SemIR::File members.

+ 11 - 1
toolchain/check/cpp/generate_ast.cpp

@@ -35,6 +35,7 @@
 #include "toolchain/diagnostics/format_providers.h"
 #include "toolchain/parse/node_ids.h"
 #include "toolchain/sem_ir/cpp_file.h"
+#include "toolchain/sem_ir/mangler.h"
 
 namespace Carbon::Check {
 
@@ -424,12 +425,21 @@ auto CarbonExternalASTSource::MapInstIdToClangDecl(
           cpp_return_type, cpp_param_types,
           clang::FunctionProtoType::ExtProtoInfo());
 
-      return clang::FunctionDecl::Create(
+      auto* function_decl = clang::FunctionDecl::Create(
           *ast_context_, &decl_context,
           /*StartLoc=*/clang::SourceLocation(),
           /*NLoc=*/clang::SourceLocation(),
           clang::DeclarationName(identifier_info), cpp_function_type,
           /*TInfo=*/nullptr, clang::SC_Extern);
+
+      // Mangle the function name and attach it to the `FunctionDecl`.
+      SemIR::Mangler m(context_->sem_ir(), context_->total_ir_count());
+      std::string mangled_name =
+          m.Mangle(callee_function->function_id, SemIR::SpecificId::None);
+      function_decl->addAttr(
+          clang::AsmLabelAttr::Create(*ast_context_, mangled_name));
+
+      return function_decl;
     }
     default:
       return nullptr;

+ 1 - 2
toolchain/lower/BUILD

@@ -47,8 +47,6 @@ cc_library(
         "context.cpp",
         "file_context.cpp",
         "function_context.cpp",
-        "mangler.cpp",
-        "mangler.h",
         "specific_coalescer.cpp",
     ] +
     # Glob handler files to avoid missing any.
@@ -80,6 +78,7 @@ cc_library(
         "//toolchain/sem_ir:expr_info",
         "//toolchain/sem_ir:file",
         "//toolchain/sem_ir:inst_namer",
+        "//toolchain/sem_ir:mangler",
         "//toolchain/sem_ir:stringify",
         "//toolchain/sem_ir:typed_insts",
         "@llvm-project//clang:ast",

+ 4 - 4
toolchain/lower/file_context.cpp

@@ -22,7 +22,6 @@
 #include "toolchain/lower/clang_global_decl.h"
 #include "toolchain/lower/constant.h"
 #include "toolchain/lower/function_context.h"
-#include "toolchain/lower/mangler.h"
 #include "toolchain/lower/options.h"
 #include "toolchain/lower/specific_coalescer.h"
 #include "toolchain/sem_ir/absolute_node_id.h"
@@ -36,6 +35,7 @@
 #include "toolchain/sem_ir/inst.h"
 #include "toolchain/sem_ir/inst_categories.h"
 #include "toolchain/sem_ir/inst_kind.h"
+#include "toolchain/sem_ir/mangler.h"
 #include "toolchain/sem_ir/pattern.h"
 #include "toolchain/sem_ir/stringify.h"
 #include "toolchain/sem_ir/typed_insts.h"
@@ -714,7 +714,7 @@ auto FileContext::GetOrCreateLLVMFunction(
         sem_ir().clang_decls().Get(clang_decl_id).key.decl->getAsFunction());
   }
 
-  Mangler m(*this);
+  SemIR::Mangler m(sem_ir(), context().total_ir_count());
   std::string mangled_name = m.Mangle(function_id, specific_id);
   if (auto* existing = llvm_module().getFunction(mangled_name)) {
     // We might have already lowered this function while lowering a different
@@ -1244,7 +1244,7 @@ auto FileContext::BuildGlobalVariableDecl(SemIR::VarStorage var_storage)
 
 auto FileContext::BuildNonCppGlobalVariableDecl(SemIR::VarStorage var_storage)
     -> llvm::GlobalVariable* {
-  Mangler m(*this);
+  SemIR::Mangler m(sem_ir(), context().total_ir_count());
   auto mangled_name = m.MangleGlobalVariable(var_storage.pattern_id);
   auto linkage = llvm::GlobalVariable::ExternalLinkage;
 
@@ -1289,7 +1289,7 @@ auto FileContext::BuildVtable(const SemIR::Vtable& vtable,
     -> llvm::GlobalVariable* {
   const auto& class_info = sem_ir().classes().Get(vtable.class_id);
 
-  Mangler m(*this);
+  SemIR::Mangler m(sem_ir(), context().total_ir_count());
   std::string mangled_name = m.MangleVTable(class_info, specific_id);
 
   if (sem_ir()

+ 2 - 6
toolchain/lower/testdata/interop/cpp/reverse/function.carbon

@@ -20,8 +20,6 @@ library "[[@TEST_NAME]]";
 import Other;
 import Cpp inline '''
 void G() {
-  // TODO: this is not actually calling the Carbon function yet, because
-  // it's not using the right mangled name.
   Carbon::Other::F();
 }
 ''';
@@ -56,13 +54,11 @@ void G() {
 // CHECK:STDOUT: ; Function Attrs: mustprogress uwtable
 // CHECK:STDOUT: define dso_local void @_Z1Gv() #0 {
 // CHECK:STDOUT: entry:
-// CHECK:STDOUT:   call void @_ZN6Carbon5Other1FEv()
+// CHECK:STDOUT:   call void @_CF.Other()
 // CHECK:STDOUT:   ret void
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: declare void @_ZN6Carbon5Other1FEv() #1
-// CHECK:STDOUT:
-// CHECK:STDOUT: declare void @_CF.Other()
+// CHECK:STDOUT: declare void @_CF.Other() #1
 // CHECK:STDOUT:
 // CHECK:STDOUT: attributes #0 = { mustprogress uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
 // CHECK:STDOUT: attributes #1 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }

+ 16 - 0
toolchain/sem_ir/BUILD

@@ -346,3 +346,19 @@ cc_test(
         "@llvm-project//llvm:Support",
     ],
 )
+
+cc_library(
+    name = "mangler",
+    srcs = ["mangler.cpp"],
+    hdrs = ["mangler.h"],
+    deps = [
+        ":entry_point",
+        ":file",
+        ":inst_namer",
+        ":typed_insts",
+        "//common:raw_string_ostream",
+        "//toolchain/base:kind_switch",
+        "@llvm-project//clang:ast",
+        "@llvm-project//llvm:Support",
+    ],
+)

+ 3 - 3
toolchain/lower/mangler.cpp → toolchain/sem_ir/mangler.cpp

@@ -2,7 +2,7 @@
 // Exceptions. See /LICENSE for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
-#include "toolchain/lower/mangler.h"
+#include "toolchain/sem_ir/mangler.h"
 
 #include <string>
 
@@ -15,7 +15,7 @@
 #include "toolchain/sem_ir/specific_named_constraint.h"
 #include "toolchain/sem_ir/typed_insts.h"
 
-namespace Carbon::Lower {
+namespace Carbon::SemIR {
 
 auto Mangler::MangleNameId(llvm::raw_ostream& os, SemIR::NameId name_id)
     -> void {
@@ -286,4 +286,4 @@ auto Mangler::MangleUnqualifiedClass(llvm::raw_ostream& os,
   MangleNameId(os, class_info.name_id);
   MangleSpecificId(os, specific_id);
 }
-}  // namespace Carbon::Lower
+}  // namespace Carbon::SemIR

+ 10 - 15
toolchain/lower/mangler.h → toolchain/sem_ir/mangler.h

@@ -2,18 +2,17 @@
 // Exceptions. See /LICENSE for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
-#ifndef CARBON_TOOLCHAIN_LOWER_MANGLER_H_
-#define CARBON_TOOLCHAIN_LOWER_MANGLER_H_
+#ifndef CARBON_TOOLCHAIN_SEM_IR_MANGLER_H_
+#define CARBON_TOOLCHAIN_SEM_IR_MANGLER_H_
 
 #include <string>
 
 #include "clang/AST/Mangle.h"
-#include "toolchain/lower/file_context.h"
 #include "toolchain/sem_ir/constant.h"
 #include "toolchain/sem_ir/ids.h"
 #include "toolchain/sem_ir/inst_fingerprinter.h"
 
-namespace Carbon::Lower {
+namespace Carbon::SemIR {
 
 // A class for producing mangled (deterministically unique, at least partially
 // human readable) names for externally referenceable entities such as
@@ -21,10 +20,9 @@ namespace Carbon::Lower {
 class Mangler {
  public:
   // Initialize a new Mangler instance for mangling entities within the
-  // specified `FileContext`.
-  explicit Mangler(FileContext& file_context)
-      : file_context_(file_context),
-        fingerprinter_(file_context_.context().total_ir_count()) {}
+  // specified `File`.
+  Mangler(const SemIR::File& sem_ir, int total_ir_count)
+      : sem_ir_(sem_ir), fingerprinter_(total_ir_count) {}
 
   // Produce a deterministically unique mangled name for the function specified
   // by `function_id` and `specific_id`.
@@ -66,7 +64,7 @@ class Mangler {
   // Generates a mangled name using Clang mangling for imported C++ functions.
   auto MangleCppClang(const clang::NamedDecl* decl) -> std::string;
 
-  auto sem_ir() const -> const SemIR::File& { return file_context_.sem_ir(); }
+  auto sem_ir() const -> const SemIR::File& { return sem_ir_; }
 
   auto names() const -> SemIR::NameStoreWrapper { return sem_ir().names(); }
 
@@ -78,13 +76,10 @@ class Mangler {
     return sem_ir().constant_values();
   }
 
-  FileContext& file_context_;
-
-  // TODO: If `file_context_` has an `InstNamer`, we could share its
-  // fingerprinter.
+  const SemIR::File& sem_ir_;
   SemIR::InstFingerprinter fingerprinter_;
 };
 
-}  // namespace Carbon::Lower
+}  // namespace Carbon::SemIR
 
-#endif  // CARBON_TOOLCHAIN_LOWER_MANGLER_H_
+#endif  // CARBON_TOOLCHAIN_SEM_IR_MANGLER_H_