mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 19:40:10 +01:00
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.
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user