Skip to content

Commit f0cff61

Browse files
authored
Add support for using C++ double type in imported function declarations (#5868)
Carbon only supports f64, so only double can be mapped. https://github.com/carbon-language/carbon-lang/blob/30f0ddab71bda71f8789080962b1fe8a5938e327/toolchain/check/type.cpp#L54 C++ Interop Demo: ```c++ // hello_world.h auto hello_world(double x) -> void; ``` ```c++ // hello_world.cpp #include "hello_world.h" #include <cstdio> auto hello_world(double x) -> void { printf("double: %f\n", x); } ``` ```carbon // main.carbon library "Main"; import Cpp library "hello_world.h"; fn Run() -> i32 { Cpp.hello_world(0.25); return 0; } ``` ```shell $ clang -c hello_world.cpp $ bazel-bin/toolchain/carbon compile main.carbon $ bazel-bin/toolchain/carbon link hello_world.o main.o --output=demo $ $ ./demo double: 0.250000 ``` Before this change: ```shell $ bazel-bin/toolchain/carbon compile main.carbon main.carbon:8:3: error: semantics TODO: `Unsupported: parameter type: double` Cpp.hello_world(0.25); ^~~~~~~~~~~~~~~ main.carbon:8:3: note: in `Cpp` name lookup for `hello_world` Cpp.hello_world(0.25); ^~~~~~~~~~~~~~~ ``` Part of #5263.
1 parent ef475d8 commit f0cff61

File tree

5 files changed

+117
-19
lines changed

5 files changed

+117
-19
lines changed

toolchain/check/handle_literal.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "toolchain/check/name_lookup.h"
1313
#include "toolchain/check/type.h"
1414
#include "toolchain/diagnostics/format_providers.h"
15+
#include "toolchain/sem_ir/ids.h"
1516
#include "toolchain/sem_ir/typed_insts.h"
1617

1718
namespace Carbon::Check {
@@ -147,9 +148,8 @@ auto HandleParseNode(Context& context, Parse::FloatTypeLiteralId node_id)
147148
}
148149
auto tok_id = context.parse_tree().node_token(node_id);
149150
auto size_id = context.tokens().GetTypeLiteralSize(tok_id);
150-
auto width_id = MakeIntLiteral(context, node_id, size_id);
151-
auto fn_inst_id = LookupNameInCore(context, node_id, "Float");
152-
auto type_inst_id = PerformCall(context, node_id, fn_inst_id, {width_id});
151+
auto type_inst_id =
152+
MakeFloatTypeLiteral(context, node_id, SemIR::FloatKind::None, size_id);
153153
context.node_stack().Push(node_id, type_inst_id);
154154
return true;
155155
}

toolchain/check/import_cpp.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,15 @@ static auto MapBuiltinType(Context& context, clang::QualType qual_type,
794794
return MakeIntType(context, context.ints().Add(width), is_signed);
795795
}
796796
// TODO: Handle integer types that map to named aliases.
797+
} else if (type.isDoubleType()) {
798+
// TODO: Handle other floating point types when Carbon supports fN where N
799+
// != 64.
800+
CARBON_CHECK(ast_context.getTypeSize(qual_type) == 64);
801+
CARBON_CHECK(ast_context.hasSameType(qual_type, ast_context.DoubleTy));
802+
return ExprAsType(
803+
context, Parse::NodeId::None,
804+
MakeFloatTypeLiteral(context, Parse::NodeId::None,
805+
SemIR::FloatKind::None, context.ints().Add(64)));
797806
}
798807

799808
return {.inst_id = SemIR::TypeInstId::None, .type_id = SemIR::TypeId::None};

toolchain/check/literal.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "toolchain/check/convert.h"
1010
#include "toolchain/check/name_lookup.h"
1111
#include "toolchain/check/type.h"
12+
#include "toolchain/sem_ir/ids.h"
1213

1314
namespace Carbon::Check {
1415

@@ -35,4 +36,13 @@ auto MakeIntType(Context& context, Parse::NodeId node_id,
3536
return ExprAsType(context, node_id, type_inst_id).type_id;
3637
}
3738

39+
auto MakeFloatTypeLiteral(Context& context, Parse::NodeId node_id,
40+
SemIR::FloatKind float_kind, IntId size_id)
41+
-> SemIR::InstId {
42+
CARBON_CHECK(float_kind == SemIR::FloatKind::None);
43+
auto width_id = MakeIntLiteral(context, node_id, size_id);
44+
auto fn_inst_id = LookupNameInCore(context, node_id, "Float");
45+
return PerformCall(context, node_id, fn_inst_id, {width_id});
46+
}
47+
3848
} // namespace Carbon::Check

toolchain/check/literal.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ auto MakeIntTypeLiteral(Context& context, Parse::NodeId node_id,
2424
auto MakeIntType(Context& context, Parse::NodeId node_id,
2525
SemIR::IntKind int_kind, IntId size_id) -> SemIR::TypeId;
2626

27+
// Forms a floating point type expression for `fN` literal.
28+
auto MakeFloatTypeLiteral(Context& context, Parse::NodeId node_id,
29+
SemIR::FloatKind float_kind, IntId size_id)
30+
-> SemIR::InstId;
31+
2732
} // namespace Carbon::Check
2833

2934
#endif // CARBON_TOOLCHAIN_CHECK_LITERAL_H_

toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon

Lines changed: 90 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,26 @@ fn F() {
358358
//@dump-sem-ir-end
359359
}
360360

361+
// ============================================================================
362+
// double param
363+
// ============================================================================
364+
365+
// --- double_param.h
366+
367+
auto foo(double a) -> void;
368+
369+
// --- import_double_param.carbon
370+
371+
library "[[@TEST_NAME]]";
372+
373+
import Cpp library "double_param.h";
374+
375+
fn F() {
376+
//@dump-sem-ir-begin
377+
Cpp.foo(0.8 as f64);
378+
//@dump-sem-ir-end
379+
}
380+
361381
// ============================================================================
362382
// bool return
363383
// ============================================================================
@@ -399,29 +419,22 @@ fn F() {
399419
}
400420

401421
// ============================================================================
402-
// float return
422+
// double return
403423
// ============================================================================
404424

405-
// --- float_return.h
425+
// --- double_return.h
406426

407-
auto foo_float() -> float;
427+
auto foo_double() -> double;
408428

409-
// --- fail_todo_import_float_return.carbon
429+
// --- import_double_return.carbon
410430

411431
library "[[@TEST_NAME]]";
412432

413-
import Cpp library "float_return.h";
433+
import Cpp library "double_return.h";
414434

415435
fn F() {
416436
//@dump-sem-ir-begin
417-
// CHECK:STDERR: fail_todo_import_float_return.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: return type: float` [SemanticsTodo]
418-
// CHECK:STDERR: Cpp.foo_float();
419-
// CHECK:STDERR: ^~~~~~~~~~~~~
420-
// CHECK:STDERR: fail_todo_import_float_return.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo_float` [InCppNameLookup]
421-
// CHECK:STDERR: Cpp.foo_float();
422-
// CHECK:STDERR: ^~~~~~~~~~~~~
423-
// CHECK:STDERR:
424-
Cpp.foo_float();
437+
let x: f64 = Cpp.foo_double();
425438
//@dump-sem-ir-end
426439
}
427440

@@ -1074,6 +1087,43 @@ fn F() {
10741087
// CHECK:STDOUT: <elided>
10751088
// CHECK:STDOUT: }
10761089
// CHECK:STDOUT:
1090+
// CHECK:STDOUT: --- import_double_param.carbon
1091+
// CHECK:STDOUT:
1092+
// CHECK:STDOUT: constants {
1093+
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
1094+
// CHECK:STDOUT: %int_64: Core.IntLiteral = int_value 64 [concrete]
1095+
// CHECK:STDOUT: %Float.type: type = fn_type @Float [concrete]
1096+
// CHECK:STDOUT: %Float: %Float.type = struct_value () [concrete]
1097+
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
1098+
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
1099+
// CHECK:STDOUT: %float: f64 = float_literal 0.80000000000000004 [concrete]
1100+
// CHECK:STDOUT: }
1101+
// CHECK:STDOUT:
1102+
// CHECK:STDOUT: imports {
1103+
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
1104+
// CHECK:STDOUT: .foo = %foo.decl
1105+
// CHECK:STDOUT: import Cpp//...
1106+
// CHECK:STDOUT: }
1107+
// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {
1108+
// CHECK:STDOUT: <elided>
1109+
// CHECK:STDOUT: } {
1110+
// CHECK:STDOUT: <elided>
1111+
// CHECK:STDOUT: }
1112+
// CHECK:STDOUT: }
1113+
// CHECK:STDOUT:
1114+
// CHECK:STDOUT: fn @F() {
1115+
// CHECK:STDOUT: !entry:
1116+
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
1117+
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
1118+
// CHECK:STDOUT: %float: f64 = float_literal 0.80000000000000004 [concrete = constants.%float]
1119+
// CHECK:STDOUT: %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
1120+
// CHECK:STDOUT: %Float.call: init type = call constants.%Float(%int_64) [concrete = f64]
1121+
// CHECK:STDOUT: %.loc8_18.1: type = value_of_initializer %Float.call [concrete = f64]
1122+
// CHECK:STDOUT: %.loc8_18.2: type = converted %Float.call, %.loc8_18.1 [concrete = f64]
1123+
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(%float)
1124+
// CHECK:STDOUT: <elided>
1125+
// CHECK:STDOUT: }
1126+
// CHECK:STDOUT:
10771127
// CHECK:STDOUT: --- import_bool_return.carbon
10781128
// CHECK:STDOUT:
10791129
// CHECK:STDOUT: constants {
@@ -1155,22 +1205,46 @@ fn F() {
11551205
// CHECK:STDOUT: <elided>
11561206
// CHECK:STDOUT: }
11571207
// CHECK:STDOUT:
1158-
// CHECK:STDOUT: --- fail_todo_import_float_return.carbon
1208+
// CHECK:STDOUT: --- import_double_return.carbon
11591209
// CHECK:STDOUT:
11601210
// CHECK:STDOUT: constants {
1211+
// CHECK:STDOUT: %int_64: Core.IntLiteral = int_value 64 [concrete]
1212+
// CHECK:STDOUT: %Float.type: type = fn_type @Float [concrete]
1213+
// CHECK:STDOUT: %Float: %Float.type = struct_value () [concrete]
1214+
// CHECK:STDOUT: %pattern_type.3de: type = pattern_type f64 [concrete]
1215+
// CHECK:STDOUT: %foo_double.type: type = fn_type @foo_double [concrete]
1216+
// CHECK:STDOUT: %foo_double: %foo_double.type = struct_value () [concrete]
11611217
// CHECK:STDOUT: }
11621218
// CHECK:STDOUT:
11631219
// CHECK:STDOUT: imports {
11641220
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
1165-
// CHECK:STDOUT: .foo_float = <error>
1221+
// CHECK:STDOUT: .foo_double = %foo_double.decl
11661222
// CHECK:STDOUT: import Cpp//...
11671223
// CHECK:STDOUT: }
1224+
// CHECK:STDOUT: %foo_double.decl: %foo_double.type = fn_decl @foo_double [concrete = constants.%foo_double] {
1225+
// CHECK:STDOUT: <elided>
1226+
// CHECK:STDOUT: } {
1227+
// CHECK:STDOUT: <elided>
1228+
// CHECK:STDOUT: }
11681229
// CHECK:STDOUT: }
11691230
// CHECK:STDOUT:
11701231
// CHECK:STDOUT: fn @F() {
11711232
// CHECK:STDOUT: !entry:
1233+
// CHECK:STDOUT: name_binding_decl {
1234+
// CHECK:STDOUT: %x.patt: %pattern_type.3de = binding_pattern x [concrete]
1235+
// CHECK:STDOUT: }
11721236
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
1173-
// CHECK:STDOUT: %foo_float.ref: <error> = name_ref foo_float, <error> [concrete = <error>]
1237+
// CHECK:STDOUT: %foo_double.ref: %foo_double.type = name_ref foo_double, imports.%foo_double.decl [concrete = constants.%foo_double]
1238+
// CHECK:STDOUT: %foo_double.call: init f64 = call %foo_double.ref()
1239+
// CHECK:STDOUT: %.loc8_10.1: type = splice_block %.loc8_10.3 [concrete = f64] {
1240+
// CHECK:STDOUT: %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
1241+
// CHECK:STDOUT: %Float.call: init type = call constants.%Float(%int_64) [concrete = f64]
1242+
// CHECK:STDOUT: %.loc8_10.2: type = value_of_initializer %Float.call [concrete = f64]
1243+
// CHECK:STDOUT: %.loc8_10.3: type = converted %Float.call, %.loc8_10.2 [concrete = f64]
1244+
// CHECK:STDOUT: }
1245+
// CHECK:STDOUT: %.loc8_31.1: f64 = value_of_initializer %foo_double.call
1246+
// CHECK:STDOUT: %.loc8_31.2: f64 = converted %foo_double.call, %.loc8_31.1
1247+
// CHECK:STDOUT: %x: f64 = bind_name x, %.loc8_31.2
11741248
// CHECK:STDOUT: <elided>
11751249
// CHECK:STDOUT: }
11761250
// CHECK:STDOUT:

0 commit comments

Comments
 (0)