mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 22:02:23 +01:00
Export Carbon global variables and static vars to C++ (#7298)
Add `ExportVarToCpp`. This checks the `clang_decls` mapping and returns an existing decl if found. Otherwise, it creates a new `VarDecl` and adds it to the `clang_decls` mapping. When lowering, in `FileContext::BuildGlobalVariableDecl`, the `clang_decls` mapping is used to lookup an existing `llvm::GlobalVariable` for the instruction. If found, use that rather than creating a new one to avoid an unwanted second definition in the llvm IR.
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
#include "toolchain/check/type.h"
|
||||
#include "toolchain/sem_ir/generic.h"
|
||||
#include "toolchain/sem_ir/mangler.h"
|
||||
#include "toolchain/sem_ir/pattern.h"
|
||||
#include "toolchain/sem_ir/typed_insts.h"
|
||||
#include "toolchain/sem_ir/vtable.h"
|
||||
|
||||
@@ -937,4 +938,66 @@ auto ExportDestructorToCpp(Context& context, const SemIR::Class& class_info,
|
||||
return cpp_destructor_decl;
|
||||
}
|
||||
|
||||
auto ExportVarToCpp(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::VarStorage var_storage) -> clang::VarDecl* {
|
||||
// Check if the variable was already exported and return the existing
|
||||
// `VarDecl` if so. Note that the `pattern_id` is used as the key
|
||||
// rather than the `InstId` for the `VarStorage`. This just makes
|
||||
// lookup more convenient in places where the `VarStorage` `InstId` is
|
||||
// not readily accessible.
|
||||
auto clang_decl_id = context.clang_decls().Lookup(var_storage.pattern_id);
|
||||
if (clang_decl_id.has_value()) {
|
||||
return cast<clang::VarDecl>(
|
||||
context.clang_decls().Get(clang_decl_id).key.decl);
|
||||
}
|
||||
|
||||
// Look up the entity name and check the scope.
|
||||
auto entity_name_id = GetFirstBindingNameFromPatternId(
|
||||
context.sem_ir(), var_storage.pattern_id);
|
||||
const auto& entity_name = context.entity_names().Get(entity_name_id);
|
||||
auto scope_inst = context.insts().Get(
|
||||
context.name_scopes().Get(entity_name.parent_scope_id).inst_id());
|
||||
CARBON_CHECK(scope_inst.Is<SemIR::Namespace>() ||
|
||||
scope_inst.Is<SemIR::ClassDecl>());
|
||||
|
||||
// Map the parent scope into the C++ AST.
|
||||
auto* decl_context =
|
||||
ExportNameScopeToCpp(context, loc_id, entity_name.parent_scope_id);
|
||||
if (!decl_context) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Map the type.
|
||||
auto cpp_type = MapToCppType(context, var_storage.type_id);
|
||||
if (cpp_type.isNull()) {
|
||||
context.TODO(loc_id, "failed to map Carbon type to C++");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create the `clang::VarDecl` and add it to `clang_decls()`.
|
||||
auto clang_loc = GetCppLocation(context, loc_id);
|
||||
auto* identifier_info = GetClangIdentifierInfo(context, entity_name.name_id);
|
||||
auto* var_decl = clang::VarDecl::Create(
|
||||
context.ast_context(), decl_context,
|
||||
/*StartLoc=*/clang_loc, /*IdLoc=*/clang_loc, identifier_info, cpp_type,
|
||||
/*TInfo=*/nullptr, clang::SC_Extern);
|
||||
context.clang_decls().Add(
|
||||
{.key = SemIR::ClangDeclKey::ForNonFunctionDecl(var_decl),
|
||||
.inst_id = var_storage.pattern_id});
|
||||
|
||||
if (scope_inst.Is<SemIR::ClassDecl>()) {
|
||||
// TODO: Map Carbon access to C++ access.
|
||||
var_decl->setAccess(clang::AS_public);
|
||||
}
|
||||
|
||||
// Set the Carbon mangled variable name.
|
||||
SemIR::Mangler m(context.sem_ir(), context.total_ir_count(),
|
||||
context.mangle_string_fingerprint());
|
||||
std::string mangled_name = m.MangleGlobalVariable(var_storage.pattern_id);
|
||||
var_decl->addAttr(
|
||||
clang::AsmLabelAttr::Create(context.ast_context(), mangled_name));
|
||||
|
||||
return var_decl;
|
||||
}
|
||||
|
||||
} // namespace Carbon::Check
|
||||
|
||||
Reference in New Issue
Block a user