Skip to content

Commit 4d4d720

Browse files
authored
C++ Interop: Support getting void* from C++ functions and passing void* it to C++ function (#6279)
This defines `Cpp.void` as a custom type. `Cpp.void*` is mapped to C++ `void*`. Not supported yet: Conversions from and to other pointer types. C++ Interop Demo: ```carbon // main.carbon library "Main"; import Core library "io"; import Cpp inline ''' #include <cstdio> auto GetPointer() -> void* _Nonnull { static int x = 8; return &x; } auto GetValue(void* _Nonnull ptr) -> int { return *static_cast<int*>(ptr); } '''; fn Run() -> i32 { let ptr: Cpp.void* = Cpp.GetPointer(); Core.Print(Cpp.GetValue(ptr)); return 0; } ``` ```shell $ bazel-bin/toolchain/carbon compile main.carbon $ bazel-bin/toolchain/carbon link main.o --output=demo $ ./demo 8 ``` Part of #6280.
1 parent 29d7e52 commit 4d4d720

24 files changed

+2653
-1982
lines changed

toolchain/check/cpp/import.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,6 +1137,9 @@ static auto MapBuiltinType(Context& context, SemIR::LocId loc_id,
11371137
context.ints().Add(ast_context.getTypeSize(qual_type))));
11381138
}
11391139
// TODO: Handle floating-point types that map to named aliases.
1140+
} else if (type.isVoidType()) {
1141+
return ExprAsType(context, Parse::NodeId::None,
1142+
SemIR::CppVoidType::TypeInstId);
11401143
}
11411144

11421145
return TypeExpr::None;
@@ -2116,6 +2119,7 @@ static auto LookupBuiltinTypes(Context& context, SemIR::LocId loc_id,
21162119
.Case("float", ast_context.FloatTy)
21172120
.Case("double", ast_context.DoubleTy)
21182121
.Case("long_double", ast_context.LongDoubleTy)
2122+
.Case("void", ast_context.VoidTy)
21192123
.Default(clang::QualType());
21202124
if (builtin_type.isNull()) {
21212125
return SemIR::InstId::None;

toolchain/check/cpp/type_mapping.cpp

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,33 @@ static auto MapNonWrapperType(Context& context, SemIR::InstId inst_id,
195195
}
196196
}
197197

198+
// Returns `void*` if the type is a wrapped `Cpp.void*`, consuming the pointer
199+
// from `wrapper_types`. Otherwise returns no type.
200+
static auto TryMapVoidPointer(Context& context, SemIR::TypeId type_id,
201+
llvm::SmallVector<SemIR::TypeId>& wrapper_types)
202+
-> clang::QualType {
203+
if (type_id != SemIR::CppVoidType::TypeId || wrapper_types.empty()) {
204+
return clang::QualType();
205+
}
206+
207+
if (context.types().Is<SemIR::PointerType>(wrapper_types.back())) {
208+
// `void*`.
209+
wrapper_types.pop_back();
210+
} else if (wrapper_types.size() >= 2 &&
211+
context.types().Is<SemIR::ConstType>(wrapper_types.back()) &&
212+
context.types().Is<SemIR::PointerType>(
213+
wrapper_types[wrapper_types.size() - 2])) {
214+
// `const void*`.
215+
wrapper_types.erase(wrapper_types.end() - 2);
216+
} else {
217+
return clang::QualType();
218+
}
219+
220+
return context.ast_context().getAttributedType(
221+
clang::attr::TypeNonNull, context.ast_context().VoidPtrTy,
222+
context.ast_context().VoidPtrTy);
223+
}
224+
198225
// Maps a Carbon type to a C++ type. Accepts an InstId, representing a value
199226
// whose type is mapped to a C++ type. Returns `clang::QualType` if the mapping
200227
// succeeds, or `clang::QualType::isNull()` if the type is not supported.
@@ -219,9 +246,13 @@ static auto MapToCppType(Context& context, SemIR::InstId inst_id)
219246
wrapper_types.push_back(orig_type_id);
220247
}
221248

222-
clang::QualType mapped_type = MapNonWrapperType(context, inst_id, type_id);
249+
clang::QualType mapped_type =
250+
TryMapVoidPointer(context, type_id, wrapper_types);
223251
if (mapped_type.isNull()) {
224-
return mapped_type;
252+
mapped_type = MapNonWrapperType(context, inst_id, type_id);
253+
if (mapped_type.isNull()) {
254+
return mapped_type;
255+
}
225256
}
226257

227258
for (auto wrapper_type_id : llvm::reverse(wrapper_types)) {

toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
// CHECK:STDOUT: import_ir_insts: {}
2121
// CHECK:STDOUT: clang_decls: {}
2222
// CHECK:STDOUT: name_scopes:
23-
// CHECK:STDOUT: name_scope00000000: {inst: inst0000000E, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {}}
23+
// CHECK:STDOUT: name_scope00000000: {inst: inst0000000F, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {}}
2424
// CHECK:STDOUT: entity_names: {}
2525
// CHECK:STDOUT: cpp_global_vars: {}
2626
// CHECK:STDOUT: functions: {}
@@ -42,6 +42,7 @@
4242
// CHECK:STDOUT: 'inst(BoolType)': {kind: BoolType, type: type(TypeType)}
4343
// CHECK:STDOUT: 'inst(BoundMethodType)': {kind: BoundMethodType, type: type(TypeType)}
4444
// CHECK:STDOUT: 'inst(CharLiteralType)': {kind: CharLiteralType, type: type(TypeType)}
45+
// CHECK:STDOUT: 'inst(CppVoidType)': {kind: CppVoidType, type: type(TypeType)}
4546
// CHECK:STDOUT: 'inst(ErrorInst)': {kind: ErrorInst, type: type(Error)}
4647
// CHECK:STDOUT: 'inst(FloatLiteralType)': {kind: FloatLiteralType, type: type(TypeType)}
4748
// CHECK:STDOUT: 'inst(ImplWitnessTablePlaceholder)': {kind: ImplWitnessTablePlaceholder, type: type(TypeType)}
@@ -51,14 +52,15 @@
5152
// CHECK:STDOUT: 'inst(SpecificFunctionType)': {kind: SpecificFunctionType, type: type(TypeType)}
5253
// CHECK:STDOUT: 'inst(VtableType)': {kind: VtableType, type: type(TypeType)}
5354
// CHECK:STDOUT: 'inst(WitnessType)': {kind: WitnessType, type: type(TypeType)}
54-
// CHECK:STDOUT: inst0000000E: {kind: Namespace, arg0: name_scope00000000, arg1: inst<none>, type: type(inst(NamespaceType))}
55+
// CHECK:STDOUT: inst0000000F: {kind: Namespace, arg0: name_scope00000000, arg1: inst<none>, type: type(inst(NamespaceType))}
5556
// CHECK:STDOUT: constant_values:
5657
// CHECK:STDOUT: values:
5758
// CHECK:STDOUT: 'inst(TypeType)': concrete_constant(inst(TypeType))
5859
// CHECK:STDOUT: 'inst(AutoType)': concrete_constant(inst(AutoType))
5960
// CHECK:STDOUT: 'inst(BoolType)': concrete_constant(inst(BoolType))
6061
// CHECK:STDOUT: 'inst(BoundMethodType)': concrete_constant(inst(BoundMethodType))
6162
// CHECK:STDOUT: 'inst(CharLiteralType)': concrete_constant(inst(CharLiteralType))
63+
// CHECK:STDOUT: 'inst(CppVoidType)': concrete_constant(inst(CppVoidType))
6264
// CHECK:STDOUT: 'inst(ErrorInst)': concrete_constant(inst(ErrorInst))
6365
// CHECK:STDOUT: 'inst(FloatLiteralType)': concrete_constant(inst(FloatLiteralType))
6466
// CHECK:STDOUT: 'inst(ImplWitnessTablePlaceholder)': concrete_constant(inst(ImplWitnessTablePlaceholder))
@@ -68,13 +70,13 @@
6870
// CHECK:STDOUT: 'inst(SpecificFunctionType)': concrete_constant(inst(SpecificFunctionType))
6971
// CHECK:STDOUT: 'inst(VtableType)': concrete_constant(inst(VtableType))
7072
// CHECK:STDOUT: 'inst(WitnessType)': concrete_constant(inst(WitnessType))
71-
// CHECK:STDOUT: inst0000000E: concrete_constant(inst0000000E)
73+
// CHECK:STDOUT: inst0000000F: concrete_constant(inst0000000F)
7274
// CHECK:STDOUT: symbolic_constants: {}
7375
// CHECK:STDOUT: inst_blocks:
7476
// CHECK:STDOUT: inst_block_empty: {}
7577
// CHECK:STDOUT: exports: {}
7678
// CHECK:STDOUT: imports: {}
7779
// CHECK:STDOUT: global_init: {}
7880
// CHECK:STDOUT: inst_block60000004:
79-
// CHECK:STDOUT: 0: inst0000000E
81+
// CHECK:STDOUT: 0: inst0000000F
8082
// CHECK:STDOUT: ...

0 commit comments

Comments
 (0)