mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Add support for C++ calling Carbon functions with parameters (#7024)
This works by generating two thunks, one in C++ and one in Carbon. For
example, given this input:
```c++
// Carbon:
fn Callme(f: f32) {}
// C++:
void F() {
// This will call `Callme__cpp_thunk`
Carbon::Callme(1.0);
}
```
These functions are generated:
```c++
// Carbon:
fn Callme__carbon_thunk(ref f: f32) {
// Call the target function.
Callme(f);
}
// C++:
// C++ declaration for the Carbon thunk.
void Callme__carbon_thunk(float& f);
void Callme__cpp_thunk(float f) {
// Call the Carbon thunk with args passed by reference.
Callme__carbon_thunk(f);
}
```
For now, all arguments are passed by reference, even if they are simple
types like pointers or i32.
Functions with non-void return types are not supported yet.
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "toolchain/base/kind_switch.h"
|
||||
#include "toolchain/check/context.h"
|
||||
#include "toolchain/check/cpp/export.h"
|
||||
#include "toolchain/check/cpp/import.h"
|
||||
#include "toolchain/check/import_ref.h"
|
||||
#include "toolchain/check/name_lookup.h"
|
||||
@@ -36,7 +37,6 @@
|
||||
#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 {
|
||||
|
||||
@@ -432,56 +432,17 @@ auto CarbonExternalASTSource::MapInstIdToClangDecl(
|
||||
if (!callee_function) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const SemIR::Function& function =
|
||||
context_->functions().Get(callee_function->function_id);
|
||||
if (function.clang_decl_id.has_value()) {
|
||||
return cast<clang::NamedDecl>(
|
||||
context_->clang_decls().Get(function.clang_decl_id).key.decl);
|
||||
}
|
||||
auto* identifier_info =
|
||||
GetClangIdentifierInfo(*context_, function.name_id);
|
||||
CARBON_CHECK(identifier_info, "function with non-identifier name {0}",
|
||||
function.name_id);
|
||||
|
||||
if (function.call_param_ranges.explicit_size() != 0) {
|
||||
context_->TODO(target_inst_id,
|
||||
"unsupported: C++ calling a Carbon function with "
|
||||
"parameters");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (function.return_type_inst_id != SemIR::TypeInstId::None) {
|
||||
context_->TODO(target_inst_id,
|
||||
"unsupported: C++ calling a Carbon function with "
|
||||
"return type other than `()`");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO: support non-empty parameter lists.
|
||||
llvm::SmallVector<clang::QualType> cpp_param_types;
|
||||
|
||||
// TODO: support non-void return types.
|
||||
auto cpp_return_type = ast_context_->VoidTy;
|
||||
|
||||
auto cpp_function_type = ast_context_->getFunctionType(
|
||||
cpp_return_type, cpp_param_types,
|
||||
clang::FunctionProtoType::ExtProtoInfo());
|
||||
|
||||
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;
|
||||
return GetReverseInteropFunctionDecl(
|
||||
*context_, SemIR::LocId(target_inst_id), decl_context,
|
||||
callee_function->function_id);
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
|
||||
Reference in New Issue
Block a user