Ver código fonte

Never ask the mangler to mangle a C++ declaration. (#6764)

This cleans up some logic that was left behind when we stopped emitting
C++ function declarations ourselves. We would ask our mangler for a
mangling for a C++ function declaration and then not use it.
Richard Smith 2 meses atrás
pai
commit
bea24a8bee

+ 66 - 66
toolchain/lower/file_context.cpp

@@ -636,6 +636,70 @@ auto FileContext::HandleReferencedSpecificFunction(
   coalescer_.CreateTypeFingerprint(specific_id, llvm_type);
 }
 
+auto FileContext::GetOrCreateLLVMFunction(
+    const FunctionTypeInfo& function_type_info, SemIR::FunctionId function_id,
+    SemIR::SpecificId specific_id) -> llvm::Function* {
+  // If this is a C++ function, tell Clang that we referenced it.
+  if (auto clang_decl_id = sem_ir().functions().Get(function_id).clang_decl_id;
+      clang_decl_id.has_value()) {
+    CARBON_CHECK(!specific_id.has_value(),
+                 "Specific functions cannot have C++ definitions");
+    return HandleReferencedCppFunction(
+        sem_ir().clang_decls().Get(clang_decl_id).key.decl->getAsFunction());
+  }
+
+  Mangler m(*this);
+  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
+    // file. That's OK.
+    // TODO: Check-fail or maybe diagnose if the two LLVM functions are not
+    // produced by declarations of the same Carbon function. Name collisions
+    // between non-private members of the same library should have been
+    // diagnosed by check if detected, but it's not clear that check will
+    // always be able to see this problem. In theory, name collisions could
+    // also occur due to fingerprint collision.
+    return existing;
+  }
+
+  // If this is a specific function, we may need to do additional work to
+  // emit its definition.
+  if (specific_id.has_value()) {
+    HandleReferencedSpecificFunction(function_id, specific_id,
+                                     function_type_info.type);
+  }
+
+  // TODO: For an imported inline function, consider generating an
+  // `available_externally` definition.
+  auto linkage = specific_id.has_value() ? llvm::Function::LinkOnceODRLinkage
+                                         : llvm::Function::ExternalLinkage;
+  if (function_id == sem_ir().global_ctor_id()) {
+    // The global constructor name would collide with global constructors for
+    // other files in the same package, so use an internal linkage symbol.
+    linkage = llvm::Function::InternalLinkage;
+  }
+
+  auto* llvm_function = llvm::Function::Create(function_type_info.type, linkage,
+                                               mangled_name, llvm_module());
+  CARBON_CHECK(llvm_function->getName() == mangled_name,
+               "Mangled name collision: {0}", mangled_name);
+
+  // Set up parameters and the return slot.
+  for (auto [inst_id, arg] :
+       llvm::zip_equal(function_type_info.lowered_param_pattern_ids,
+                       llvm_function->args())) {
+    arg.setName(sem_ir().names().GetIRBaseName(
+        SemIR::GetPrettyNameFromPatternId(sem_ir(), inst_id)));
+  }
+  if (function_type_info.sret_type != nullptr) {
+    auto& return_arg = *llvm_function->args().begin();
+    return_arg.addAttr(llvm::Attribute::getWithStructRetType(
+        llvm_context(), function_type_info.sret_type));
+  }
+
+  return llvm_function;
+}
+
 auto FileContext::BuildFunctionDecl(SemIR::FunctionId function_id,
                                     SemIR::SpecificId specific_id)
     -> std::optional<FunctionInfo> {
@@ -665,72 +729,8 @@ auto FileContext::BuildFunctionDecl(SemIR::FunctionId function_id,
 
   auto function_type_info =
       FunctionTypeInfoBuilder(this, specific_id).Build(function);
-
-  // TODO: For an imported inline function, consider generating an
-  // `available_externally` definition.
-  auto linkage = specific_id.has_value() ? llvm::Function::LinkOnceODRLinkage
-                                         : llvm::Function::ExternalLinkage;
-  if (function_id == sem_ir().global_ctor_id()) {
-    // The global constructor name would collide with global constructors for
-    // other files in the same package, so use an internal linkage symbol.
-    linkage = llvm::Function::InternalLinkage;
-  }
-
-  Mangler m(*this);
-  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
-    // file. That's OK.
-    // TODO: Check-fail or maybe diagnose if the two LLVM functions are not
-    // produced by declarations of the same Carbon function. Name collisions
-    // between non-private members of the same library should have been
-    // diagnosed by check if detected, but it's not clear that check will always
-    // be able to see this problem. In theory, name collisions could also occur
-    // due to fingerprint collision.
-    return {{.type = function_type_info.type,
-             .di_type = function_type_info.di_type,
-             .lowered_param_pattern_ids =
-                 std::move(function_type_info.lowered_param_pattern_ids),
-             .unused_param_pattern_ids =
-                 std::move(function_type_info.unused_param_pattern_ids),
-             .llvm_function = existing}};
-  }
-
-  llvm::Function* llvm_function;
-  // If this is a C++ function, tell Clang that we referenced it.
-  if (auto clang_decl_id = sem_ir().functions().Get(function_id).clang_decl_id;
-      clang_decl_id.has_value()) {
-    CARBON_CHECK(!specific_id.has_value(),
-                 "Specific functions cannot have C++ definitions");
-    llvm_function = HandleReferencedCppFunction(
-        sem_ir().clang_decls().Get(clang_decl_id).key.decl->getAsFunction());
-  } else {
-    // If this is a specific function, we may need to do additional work to emit
-    // its definition.
-    if (specific_id.has_value()) {
-      HandleReferencedSpecificFunction(function_id, specific_id,
-                                       function_type_info.type);
-    }
-
-    llvm_function = llvm::Function::Create(function_type_info.type, linkage,
-                                           mangled_name, llvm_module());
-
-    CARBON_CHECK(llvm_function->getName() == mangled_name,
-                 "Mangled name collision: {0}", mangled_name);
-
-    // Set up parameters and the return slot.
-    for (auto [inst_id, arg] :
-         llvm::zip_equal(function_type_info.lowered_param_pattern_ids,
-                         llvm_function->args())) {
-      arg.setName(sem_ir().names().GetIRBaseName(
-          SemIR::GetPrettyNameFromPatternId(sem_ir(), inst_id)));
-    }
-    if (function_type_info.sret_type != nullptr) {
-      auto& return_arg = *llvm_function->args().begin();
-      return_arg.addAttr(llvm::Attribute::getWithStructRetType(
-          llvm_context(), function_type_info.sret_type));
-    }
-  }
+  auto* llvm_function =
+      GetOrCreateLLVMFunction(function_type_info, function_id, specific_id);
 
   return {{.type = function_type_info.type,
            .di_type = function_type_info.di_type,

+ 8 - 0
toolchain/lower/file_context.h

@@ -209,6 +209,14 @@ class FileContext {
 
   class FunctionTypeInfoBuilder;
 
+  // Builds an LLVM function declaration for the given function, or returns an
+  // existing one if we've already lowered another declaration of the same
+  // function.
+  auto GetOrCreateLLVMFunction(const FunctionTypeInfo& function_type_info,
+                               SemIR::FunctionId function_id,
+                               SemIR::SpecificId specific_id)
+      -> llvm::Function*;
+
   // Builds the declaration for the given function, which should then be cached
   // by the caller.
   auto BuildFunctionDecl(

+ 3 - 17
toolchain/lower/mangler.cpp

@@ -8,8 +8,6 @@
 
 #include "common/raw_string_ostream.h"
 #include "toolchain/base/kind_switch.h"
-#include "toolchain/lower/clang_global_decl.h"
-#include "toolchain/sem_ir/clang_decl.h"
 #include "toolchain/sem_ir/entry_point.h"
 #include "toolchain/sem_ir/ids.h"
 #include "toolchain/sem_ir/pattern.h"
@@ -177,15 +175,9 @@ auto Mangler::Mangle(SemIR::FunctionId function_id,
     return "main";
   }
 
-  // TODO: We should never need to do this: Clang should emit C++ function
-  // declarations for us.
-  if (function.clang_decl_id.has_value()) {
-    CARBON_CHECK(function.special_function_kind !=
-                     SemIR::Function::SpecialFunctionKind::HasCppThunk,
-                 "Shouldn't mangle C++ function that uses a thunk");
-    const auto& clang_decl = sem_ir().clang_decls().Get(function.clang_decl_id);
-    return MangleCppClang(cast<clang::NamedDecl>(clang_decl.key.decl));
-  }
+  // Clang should emit C++ function declarations for us.
+  CARBON_CHECK(!function.clang_decl_id.has_value(),
+               "Shouldn't mangle C++ function");
 
   RawStringOstream os;
   os << "_C";
@@ -255,12 +247,6 @@ auto Mangler::MangleGlobalVariable(SemIR::InstId pattern_id) -> std::string {
   return os.TakeStr();
 }
 
-auto Mangler::MangleCppClang(const clang::NamedDecl* decl) -> std::string {
-  return file_context_.cpp_code_generator()
-      .GetMangledName(CreateGlobalDecl(decl))
-      .str();
-}
-
 auto Mangler::MangleVTable(const SemIR::Class& class_info,
                            SemIR::SpecificId specific_id) -> std::string {
   RawStringOstream os;