diff --git a/toolchain/check/eval.cpp b/toolchain/check/eval.cpp index bd45f47ff4b1..9162b095a4c5 100644 --- a/toolchain/check/eval.cpp +++ b/toolchain/check/eval.cpp @@ -1005,8 +1005,9 @@ static auto MakeFloatTypeResult(Context& context, SemIR::LocId loc_id, -> SemIR::ConstantId { auto result = SemIR::FloatType{ .type_id = GetSingletonType(context, SemIR::TypeType::TypeInstId), - .bit_width_id = width_id}; - if (!ValidateFloatType(context, loc_id, result)) { + .bit_width_id = width_id, + .float_kind = SemIR::FloatKind::None}; + if (!ValidateFloatTypeAndSetKind(context, loc_id, result)) { return SemIR::ErrorInst::ConstantId; } return MakeConstantResult(context, result, phase); @@ -1078,9 +1079,17 @@ static auto PerformCheckedFloatConvert(Context& context, SemIR::LocId loc_id, SemIR::InstId arg_id, SemIR::TypeId dest_type_id) -> SemIR::ConstantId { + auto dest_type_object_rep_id = context.types().GetObjectRepr(dest_type_id); + CARBON_CHECK(dest_type_object_rep_id.has_value(), + "Conversion to incomplete type"); + auto dest_float_type = + context.types().TryGetAs(dest_type_object_rep_id); + CARBON_CHECK(dest_float_type || context.types().Is( + dest_type_object_rep_id)); + if (auto literal = context.insts().TryGetAs(arg_id)) { - if (context.types().Is(dest_type_id)) { + if (!dest_float_type) { return MakeConstantResult( context, SemIR::FloatLiteralValue{.type_id = dest_type_id, @@ -1105,8 +1114,7 @@ static auto PerformCheckedFloatConvert(Context& context, SemIR::LocId loc_id, real_value.exponent.toStringSigned(str); // Convert the string to an APFloat. - // TODO: Compute the fltSemantics from the type. - llvm::APFloat result(llvm::APFloat::IEEEdouble()); + llvm::APFloat result(dest_float_type->float_kind.Semantics()); // TODO: The implementation of this conversion effectively converts back to // APInts, but unfortunately the conversion from integer mantissa and // exponent in IEEEFloat::roundSignificandWithExponent is not part of the @@ -1119,27 +1127,37 @@ static auto PerformCheckedFloatConvert(Context& context, SemIR::LocId loc_id, toString(std::move(error))); } if (status.get() & llvm::APFloat::opOverflow) { - CARBON_DIAGNOSTIC(FloatTooLargeForType, Error, + CARBON_DIAGNOSTIC(FloatLiteralTooLargeForType, Error, "value {0} too large for floating-point type {1}", RealId, SemIR::TypeId); - context.emitter().Emit(loc_id, FloatTooLargeForType, literal->real_id, - dest_type_id); + context.emitter().Emit(loc_id, FloatLiteralTooLargeForType, + literal->real_id, dest_type_id); return SemIR::ErrorInst::ConstantId; } return MakeFloatResult(context, dest_type_id, std::move(result)); } - // TODO: Perform a conversion if necessary. - if (context.types().Is(dest_type_id)) { + if (!dest_float_type) { context.TODO(loc_id, "conversion from float to float literal"); return SemIR::ErrorInst::ConstantId; } + // Convert to the destination float semantics. auto arg = context.insts().GetAs(arg_id); - return MakeConstantResult( - context, - SemIR::FloatValue{.type_id = dest_type_id, .float_id = arg.float_id}, - Phase::Concrete); + llvm::APFloat result = context.floats().Get(arg.float_id); + bool loses_info; + auto status = result.convert(dest_float_type->float_kind.Semantics(), + llvm::APFloat::rmNearestTiesToEven, &loses_info); + if (status & llvm::APFloat::opOverflow) { + CARBON_DIAGNOSTIC(FloatTooLargeForType, Error, + "value {0} too large for floating-point type {1}", + llvm::APFloat, SemIR::TypeId); + context.emitter().Emit(loc_id, FloatTooLargeForType, + context.floats().Get(arg.float_id), dest_type_id); + return SemIR::ErrorInst::ConstantId; + } + + return MakeFloatResult(context, dest_type_id, std::move(result)); } // Issues a diagnostic for a compile-time division by zero. diff --git a/toolchain/check/eval_inst.cpp b/toolchain/check/eval_inst.cpp index bd5f38fa0680..374dde8da2ac 100644 --- a/toolchain/check/eval_inst.cpp +++ b/toolchain/check/eval_inst.cpp @@ -205,7 +205,7 @@ auto EvalConstantInst(Context& context, SemIR::FacetAccessType inst) auto EvalConstantInst(Context& context, SemIR::InstId inst_id, SemIR::FloatType inst) -> ConstantEvalResult { - return ValidateFloatType(context, SemIR::LocId(inst_id), inst) + return ValidateFloatTypeAndSetKind(context, SemIR::LocId(inst_id), inst) ? ConstantEvalResult::NewSamePhase(inst) : ConstantEvalResult::Error; } diff --git a/toolchain/check/handle_literal.cpp b/toolchain/check/handle_literal.cpp index f0023e52ef71..753021622d6f 100644 --- a/toolchain/check/handle_literal.cpp +++ b/toolchain/check/handle_literal.cpp @@ -121,8 +121,7 @@ auto HandleParseNode(Context& context, Parse::FloatTypeLiteralId node_id) -> bool { auto tok_id = context.parse_tree().node_token(node_id); auto size_id = context.tokens().GetTypeLiteralSize(tok_id); - auto type_inst_id = - MakeFloatTypeLiteral(context, node_id, SemIR::FloatKind::None, size_id); + auto type_inst_id = MakeFloatTypeLiteral(context, node_id, size_id); context.node_stack().Push(node_id, type_inst_id); return true; } diff --git a/toolchain/check/import_cpp.cpp b/toolchain/check/import_cpp.cpp index ce11c7eb3b3e..1720d9065f7d 100644 --- a/toolchain/check/import_cpp.cpp +++ b/toolchain/check/import_cpp.cpp @@ -1071,15 +1071,16 @@ static auto MapBuiltinType(Context& context, SemIR::LocId loc_id, return type_expr; } // TODO: Handle integer types that map to named aliases. - } else if (type.isDoubleType()) { - // TODO: Handle other floating point types when Carbon supports fN where N - // != 64. - CARBON_CHECK(ast_context.getTypeSize(qual_type) == 64); - CARBON_CHECK(ast_context.hasSameType(qual_type, ast_context.DoubleTy)); - return ExprAsType( - context, Parse::NodeId::None, - MakeFloatTypeLiteral(context, Parse::NodeId::None, - SemIR::FloatKind::None, context.ints().Add(64))); + } else if (type.isFloatingPoint()) { + if (type.isFloat16Type() || type.isFloat32Type() || type.isDoubleType() || + type.isFloat128Type()) { + return ExprAsType( + context, Parse::NodeId::None, + MakeFloatTypeLiteral( + context, Parse::NodeId::None, + context.ints().Add(ast_context.getTypeSize(qual_type)))); + } + // TODO: Handle floating-point types that map to named aliases. } return {.inst_id = SemIR::TypeInstId::None, .type_id = SemIR::TypeId::None}; diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index e01b3cdb40e0..e0ecb0ca28dc 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -1882,8 +1882,9 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, } return ResolveAsDeduplicated( - resolver, - {.type_id = SemIR::TypeType::TypeId, .bit_width_id = bit_width_id}); + resolver, {.type_id = SemIR::TypeType::TypeId, + .bit_width_id = bit_width_id, + .float_kind = inst.float_kind}); } static auto TryResolveTypedInst(ImportRefResolver& resolver, diff --git a/toolchain/check/literal.cpp b/toolchain/check/literal.cpp index e164981696f9..78b38a3dfe8a 100644 --- a/toolchain/check/literal.cpp +++ b/toolchain/check/literal.cpp @@ -38,9 +38,7 @@ auto MakeIntType(Context& context, Parse::NodeId node_id, } auto MakeFloatTypeLiteral(Context& context, Parse::NodeId node_id, - SemIR::FloatKind float_kind, IntId size_id) - -> SemIR::InstId { - CARBON_CHECK(float_kind == SemIR::FloatKind::None); + IntId size_id) -> SemIR::InstId { auto width_id = MakeIntLiteral(context, node_id, size_id); auto fn_inst_id = LookupNameInCore(context, node_id, "Float"); return PerformCall(context, node_id, fn_inst_id, {width_id}); diff --git a/toolchain/check/literal.h b/toolchain/check/literal.h index 4c617c36e7c2..c85dafaf493f 100644 --- a/toolchain/check/literal.h +++ b/toolchain/check/literal.h @@ -27,8 +27,7 @@ auto MakeIntType(Context& context, Parse::NodeId node_id, // Forms a floating point type expression for `fN` literal. auto MakeFloatTypeLiteral(Context& context, Parse::NodeId node_id, - SemIR::FloatKind float_kind, IntId size_id) - -> SemIR::InstId; + IntId size_id) -> SemIR::InstId; } // namespace Carbon::Check diff --git a/toolchain/check/testdata/builtins/float/add_assign.carbon b/toolchain/check/testdata/builtins/float/add_assign.carbon index 9ca1c1b65031..f69c9f71b7d6 100644 --- a/toolchain/check/testdata/builtins/float/add_assign.carbon +++ b/toolchain/check/testdata/builtins/float/add_assign.carbon @@ -30,13 +30,6 @@ library "[[@TEST_NAME]]"; // CHECK:STDERR: fn NotPtr(a: f64, b: f64) = "float.add_assign"; -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] -// CHECK:STDERR: adapt MakeFloat(N); -// CHECK:STDERR: ^~~~~~~~~~~~ -// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+8]]:24: note: in `f32` used here [ResolvingSpecificHere] -// CHECK:STDERR: fn MixedTypes(a: f64*, b: f32) = "float.add_assign"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: // CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.add_assign" [InvalidBuiltinSignature] // CHECK:STDERR: fn MixedTypes(a: f64*, b: f32) = "float.add_assign"; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/toolchain/check/testdata/builtins/float/convert_checked.carbon b/toolchain/check/testdata/builtins/float/convert_checked.carbon index aa8df5fd442d..d2f46d3f4a17 100644 --- a/toolchain/check/testdata/builtins/float/convert_checked.carbon +++ b/toolchain/check/testdata/builtins/float/convert_checked.carbon @@ -37,43 +37,16 @@ fn Float64ToFloat64(a: f64) -> f64 = "float.convert_checked"; fn Float64ToFloatLiteral(a: f64) -> FloatLiteral() = "float.convert_checked"; fn FloatLiteralToFloat64(a: FloatLiteral()) -> f64 = "float.convert_checked"; -// --- fail_todo_f32.carbon +// --- f32.carbon library "[[@TEST_NAME]]"; export import library "literal"; -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] -// CHECK:STDERR: adapt MakeFloat(N); -// CHECK:STDERR: ^~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_f32.carbon:[[@LINE+8]]:29: note: in `f32` used here [ResolvingSpecificHere] -// CHECK:STDERR: fn Float32ToFloat32(a: f32) -> f32 = "float.convert_checked"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: -// CHECK:STDERR: fail_todo_f32.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.convert_checked" [InvalidBuiltinSignature] -// CHECK:STDERR: fn Float32ToFloat32(a: f32) -> f32 = "float.convert_checked"; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fn Float32ToFloat32(a: f32) -> f32 = "float.convert_checked"; -// CHECK:STDERR: fail_todo_f32.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.convert_checked" [InvalidBuiltinSignature] -// CHECK:STDERR: fn Float32ToFloatLiteral(a: f32) -> FloatLiteral() = "float.convert_checked"; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fn Float32ToFloatLiteral(a: f32) -> FloatLiteral() = "float.convert_checked"; -// CHECK:STDERR: fail_todo_f32.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.convert_checked" [InvalidBuiltinSignature] -// CHECK:STDERR: fn FloatLiteralToFloat32(a: FloatLiteral()) -> f32 = "float.convert_checked"; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fn FloatLiteralToFloat32(a: FloatLiteral()) -> f32 = "float.convert_checked"; -// CHECK:STDERR: fail_todo_f32.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.convert_checked" [InvalidBuiltinSignature] -// CHECK:STDERR: fn Float32ToFloat64(a: f32) -> f64 = "float.convert_checked"; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fn Float32ToFloat64(a: f32) -> f64 = "float.convert_checked"; -// CHECK:STDERR: fail_todo_f32.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.convert_checked" [InvalidBuiltinSignature] -// CHECK:STDERR: fn Float64ToFloat32(a: f64) -> f32 = "float.convert_checked"; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fn Float64ToFloat32(a: f64) -> f32 = "float.convert_checked"; // --- literal_f64.carbon @@ -87,19 +60,12 @@ let b: f64 = FloatLiteralToFloat64(1.0); let c: f64 = FloatLiteralToFloat64(1.0e308); //@dump-sem-ir-end -// --- fail_todo_literal_f32.carbon +// --- literal_f32.carbon library "[[@TEST_NAME]]"; import library "f32"; //@dump-sem-ir-begin -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] -// CHECK:STDERR: adapt MakeFloat(N); -// CHECK:STDERR: ^~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_literal_f32.carbon:[[@LINE+4]]:8: note: in `f32` used here [ResolvingSpecificHere] -// CHECK:STDERR: let a: f32 = FloatLiteralToFloat32(0.0); -// CHECK:STDERR: ^~~ -// CHECK:STDERR: let a: f32 = FloatLiteralToFloat32(0.0); let b: f32 = FloatLiteralToFloat32(1.0); let c: f32 = FloatLiteralToFloat32(1.0e38); @@ -116,37 +82,23 @@ let b: f64 = Float64ToFloat64(1.0); let c: f64 = Float64ToFloat64(1.0e308); //@dump-sem-ir-end -// --- fail_todo_identity_f32.carbon +// --- identity_f32.carbon library "[[@TEST_NAME]]"; import library "f32"; //@dump-sem-ir-begin -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] -// CHECK:STDERR: adapt MakeFloat(N); -// CHECK:STDERR: ^~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_identity_f32.carbon:[[@LINE+4]]:8: note: in `f32` used here [ResolvingSpecificHere] -// CHECK:STDERR: let a: f32 = Float32ToFloat32(0.0); -// CHECK:STDERR: ^~~ -// CHECK:STDERR: let a: f32 = Float32ToFloat32(0.0); let b: f32 = Float32ToFloat32(1.0); let c: f32 = Float32ToFloat32(1.0e38); //@dump-sem-ir-end -// --- fail_todo_truncate.carbon +// --- truncate.carbon library "[[@TEST_NAME]]"; import library "f32"; //@dump-sem-ir-begin -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] -// CHECK:STDERR: adapt MakeFloat(N); -// CHECK:STDERR: ^~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_truncate.carbon:[[@LINE+4]]:8: note: in `f32` used here [ResolvingSpecificHere] -// CHECK:STDERR: let a: f32 = Float64ToFloat32(1.0); -// CHECK:STDERR: ^~~ -// CHECK:STDERR: let a: f32 = Float64ToFloat32(1.0); //@dump-sem-ir-end @@ -157,18 +109,17 @@ import library "f32"; import library "f64"; //@dump-sem-ir-begin -// TODO: These should all produce an error that the source value doesn't fit in -// the destination type. -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] -// CHECK:STDERR: adapt MakeFloat(N); -// CHECK:STDERR: ^~~~~~~~~~~~ -// CHECK:STDERR: fail_truncate_overflow.carbon:[[@LINE+4]]:8: note: in `f32` used here [ResolvingSpecificHere] +// CHECK:STDERR: fail_truncate_overflow.carbon:[[@LINE+4]]:14: error: value 9.9999999999999994E+38 too large for floating-point type `f32` [FloatTooLargeForType] // CHECK:STDERR: let a: f32 = Float64ToFloat32(1.0e39); -// CHECK:STDERR: ^~~ +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: let a: f32 = Float64ToFloat32(1.0e39); +// CHECK:STDERR: fail_truncate_overflow.carbon:[[@LINE+4]]:14: error: value 10*10^38 too large for floating-point type `f32` [FloatLiteralTooLargeForType] +// CHECK:STDERR: let b: f32 = FloatLiteralToFloat32(1.0e39); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: let b: f32 = FloatLiteralToFloat32(1.0e39); -// CHECK:STDERR: fail_truncate_overflow.carbon:[[@LINE+4]]:14: error: value 10*10^308 too large for floating-point type `f64` [FloatTooLargeForType] +// CHECK:STDERR: fail_truncate_overflow.carbon:[[@LINE+4]]:14: error: value 10*10^308 too large for floating-point type `f64` [FloatLiteralTooLargeForType] // CHECK:STDERR: let c: f64 = FloatLiteralToFloat64(1.0e309); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -309,17 +260,20 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64); // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_literal_f32.carbon +// CHECK:STDOUT: --- literal_f32.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] -// CHECK:STDOUT: %f32: type = class_type @Float, @Float(%int_32) [concrete] -// CHECK:STDOUT: %pattern_type.201: type = pattern_type %f32 [concrete] +// CHECK:STDOUT: %f32.97e: type = class_type @Float, @Float(%int_32) [concrete] +// CHECK:STDOUT: %pattern_type.201: type = pattern_type %f32.97e [concrete] // CHECK:STDOUT: %FloatLiteralToFloat32.type: type = fn_type @FloatLiteralToFloat32 [concrete] // CHECK:STDOUT: %FloatLiteralToFloat32: %FloatLiteralToFloat32.type = struct_value () [concrete] // CHECK:STDOUT: %float.1f7: Core.FloatLiteral = float_literal_value 0e-1 [concrete] +// CHECK:STDOUT: %float.4db: %f32.97e = float_value 0 [concrete] // CHECK:STDOUT: %float.674: Core.FloatLiteral = float_literal_value 10e-1 [concrete] +// CHECK:STDOUT: %float.e3b: %f32.97e = float_value 1 [concrete] // CHECK:STDOUT: %float.516: Core.FloatLiteral = float_literal_value 10e37 [concrete] +// CHECK:STDOUT: %float.520: %f32.97e = float_value 9.99999968E+37 [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -330,46 +284,46 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64); // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %a.patt: %pattern_type.201 = binding_pattern a [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc13_8: type = splice_block %f32.loc13 [concrete = constants.%f32] { -// CHECK:STDOUT: %int_32.loc13: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] -// CHECK:STDOUT: %f32.loc13: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32] +// CHECK:STDOUT: %.loc6_8: type = splice_block %f32.loc6 [concrete = constants.%f32.97e] { +// CHECK:STDOUT: %int_32.loc6: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %f32.loc6: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32.97e] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc13_39.1: %f32 = value_of_initializer @__global_init.%FloatLiteralToFloat32.call.loc13 -// CHECK:STDOUT: %.loc13_39.2: %f32 = converted @__global_init.%FloatLiteralToFloat32.call.loc13, %.loc13_39.1 -// CHECK:STDOUT: %a: %f32 = bind_name a, %.loc13_39.2 +// CHECK:STDOUT: %.loc6_39.1: %f32.97e = value_of_initializer @__global_init.%FloatLiteralToFloat32.call.loc6 [concrete = constants.%float.4db] +// CHECK:STDOUT: %.loc6_39.2: %f32.97e = converted @__global_init.%FloatLiteralToFloat32.call.loc6, %.loc6_39.1 [concrete = constants.%float.4db] +// CHECK:STDOUT: %a: %f32.97e = bind_name a, %.loc6_39.2 // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %b.patt: %pattern_type.201 = binding_pattern b [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc14_8: type = splice_block %f32.loc14 [concrete = constants.%f32] { -// CHECK:STDOUT: %int_32.loc14: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] -// CHECK:STDOUT: %f32.loc14: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32] +// CHECK:STDOUT: %.loc7_8: type = splice_block %f32.loc7 [concrete = constants.%f32.97e] { +// CHECK:STDOUT: %int_32.loc7: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %f32.loc7: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32.97e] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc14_39.1: %f32 = value_of_initializer @__global_init.%FloatLiteralToFloat32.call.loc14 -// CHECK:STDOUT: %.loc14_39.2: %f32 = converted @__global_init.%FloatLiteralToFloat32.call.loc14, %.loc14_39.1 -// CHECK:STDOUT: %b: %f32 = bind_name b, %.loc14_39.2 +// CHECK:STDOUT: %.loc7_39.1: %f32.97e = value_of_initializer @__global_init.%FloatLiteralToFloat32.call.loc7 [concrete = constants.%float.e3b] +// CHECK:STDOUT: %.loc7_39.2: %f32.97e = converted @__global_init.%FloatLiteralToFloat32.call.loc7, %.loc7_39.1 [concrete = constants.%float.e3b] +// CHECK:STDOUT: %b: %f32.97e = bind_name b, %.loc7_39.2 // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %c.patt: %pattern_type.201 = binding_pattern c [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc15_8: type = splice_block %f32.loc15 [concrete = constants.%f32] { -// CHECK:STDOUT: %int_32.loc15: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] -// CHECK:STDOUT: %f32.loc15: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32] +// CHECK:STDOUT: %.loc8_8: type = splice_block %f32.loc8 [concrete = constants.%f32.97e] { +// CHECK:STDOUT: %int_32.loc8: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %f32.loc8: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32.97e] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc15_42.1: %f32 = value_of_initializer @__global_init.%FloatLiteralToFloat32.call.loc15 -// CHECK:STDOUT: %.loc15_42.2: %f32 = converted @__global_init.%FloatLiteralToFloat32.call.loc15, %.loc15_42.1 -// CHECK:STDOUT: %c: %f32 = bind_name c, %.loc15_42.2 +// CHECK:STDOUT: %.loc8_42.1: %f32.97e = value_of_initializer @__global_init.%FloatLiteralToFloat32.call.loc8 [concrete = constants.%float.520] +// CHECK:STDOUT: %.loc8_42.2: %f32.97e = converted @__global_init.%FloatLiteralToFloat32.call.loc8, %.loc8_42.1 [concrete = constants.%float.520] +// CHECK:STDOUT: %c: %f32.97e = bind_name c, %.loc8_42.2 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %FloatLiteralToFloat32.ref.loc13: %FloatLiteralToFloat32.type = name_ref FloatLiteralToFloat32, imports.%Main.FloatLiteralToFloat32 [concrete = constants.%FloatLiteralToFloat32] -// CHECK:STDOUT: %float.loc13: Core.FloatLiteral = float_literal_value 0e-1 [concrete = constants.%float.1f7] -// CHECK:STDOUT: %FloatLiteralToFloat32.call.loc13: init %f32 = call %FloatLiteralToFloat32.ref.loc13(%float.loc13) -// CHECK:STDOUT: %FloatLiteralToFloat32.ref.loc14: %FloatLiteralToFloat32.type = name_ref FloatLiteralToFloat32, imports.%Main.FloatLiteralToFloat32 [concrete = constants.%FloatLiteralToFloat32] -// CHECK:STDOUT: %float.loc14: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float.674] -// CHECK:STDOUT: %FloatLiteralToFloat32.call.loc14: init %f32 = call %FloatLiteralToFloat32.ref.loc14(%float.loc14) -// CHECK:STDOUT: %FloatLiteralToFloat32.ref.loc15: %FloatLiteralToFloat32.type = name_ref FloatLiteralToFloat32, imports.%Main.FloatLiteralToFloat32 [concrete = constants.%FloatLiteralToFloat32] -// CHECK:STDOUT: %float.loc15: Core.FloatLiteral = float_literal_value 10e37 [concrete = constants.%float.516] -// CHECK:STDOUT: %FloatLiteralToFloat32.call.loc15: init %f32 = call %FloatLiteralToFloat32.ref.loc15(%float.loc15) +// CHECK:STDOUT: %FloatLiteralToFloat32.ref.loc6: %FloatLiteralToFloat32.type = name_ref FloatLiteralToFloat32, imports.%Main.FloatLiteralToFloat32 [concrete = constants.%FloatLiteralToFloat32] +// CHECK:STDOUT: %float.loc6: Core.FloatLiteral = float_literal_value 0e-1 [concrete = constants.%float.1f7] +// CHECK:STDOUT: %FloatLiteralToFloat32.call.loc6: init %f32.97e = call %FloatLiteralToFloat32.ref.loc6(%float.loc6) [concrete = constants.%float.4db] +// CHECK:STDOUT: %FloatLiteralToFloat32.ref.loc7: %FloatLiteralToFloat32.type = name_ref FloatLiteralToFloat32, imports.%Main.FloatLiteralToFloat32 [concrete = constants.%FloatLiteralToFloat32] +// CHECK:STDOUT: %float.loc7: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float.674] +// CHECK:STDOUT: %FloatLiteralToFloat32.call.loc7: init %f32.97e = call %FloatLiteralToFloat32.ref.loc7(%float.loc7) [concrete = constants.%float.e3b] +// CHECK:STDOUT: %FloatLiteralToFloat32.ref.loc8: %FloatLiteralToFloat32.type = name_ref FloatLiteralToFloat32, imports.%Main.FloatLiteralToFloat32 [concrete = constants.%FloatLiteralToFloat32] +// CHECK:STDOUT: %float.loc8: Core.FloatLiteral = float_literal_value 10e37 [concrete = constants.%float.516] +// CHECK:STDOUT: %FloatLiteralToFloat32.call.loc8: init %f32.97e = call %FloatLiteralToFloat32.ref.loc8(%float.loc8) [concrete = constants.%float.520] // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: @@ -480,17 +434,17 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64); // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_identity_f32.carbon +// CHECK:STDOUT: --- identity_f32.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] -// CHECK:STDOUT: %f32: type = class_type @Float, @Float(%int_32) [concrete] -// CHECK:STDOUT: %pattern_type.201: type = pattern_type %f32 [concrete] +// CHECK:STDOUT: %f32.97e: type = class_type @Float, @Float(%int_32) [concrete] +// CHECK:STDOUT: %pattern_type.201: type = pattern_type %f32.97e [concrete] // CHECK:STDOUT: %Float32ToFloat32.type: type = fn_type @Float32ToFloat32 [concrete] // CHECK:STDOUT: %Float32ToFloat32: %Float32ToFloat32.type = struct_value () [concrete] // CHECK:STDOUT: %float.1f7: Core.FloatLiteral = float_literal_value 0e-1 [concrete] -// CHECK:STDOUT: %ImplicitAs.type.31d: type = facet_type <@ImplicitAs, @ImplicitAs(%f32)> [concrete] -// CHECK:STDOUT: %ImplicitAs.Convert.type.b8c: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f32) [concrete] +// CHECK:STDOUT: %ImplicitAs.type.31d: type = facet_type <@ImplicitAs, @ImplicitAs(%f32.97e)> [concrete] +// CHECK:STDOUT: %ImplicitAs.Convert.type.b8c: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f32.97e) [concrete] // CHECK:STDOUT: %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic] // CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic] // CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644 = struct_value () [symbolic] @@ -502,15 +456,15 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64); // CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.b37: = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete] // CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] // CHECK:STDOUT: %bound_method.91e: = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] -// CHECK:STDOUT: %float.540: %f32 = float_value 0 [concrete] +// CHECK:STDOUT: %float.4db: %f32.97e = float_value 0 [concrete] // CHECK:STDOUT: %float.674: Core.FloatLiteral = float_literal_value 10e-1 [concrete] // CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.6d0: = bound_method %float.674, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete] // CHECK:STDOUT: %bound_method.6b4: = bound_method %float.674, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] -// CHECK:STDOUT: %float.3b9: %f32 = float_value 1 [concrete] +// CHECK:STDOUT: %float.e3b: %f32.97e = float_value 1 [concrete] // CHECK:STDOUT: %float.516: Core.FloatLiteral = float_literal_value 10e37 [concrete] // CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.dc9: = bound_method %float.516, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete] // CHECK:STDOUT: %bound_method.3b8: = bound_method %float.516, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] -// CHECK:STDOUT: %float.a77: %f32 = float_value 9.9999999999999997E+37 [concrete] +// CHECK:STDOUT: %float.520: %f32.97e = float_value 9.99999968E+37 [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -523,76 +477,76 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64); // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %a.patt: %pattern_type.201 = binding_pattern a [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc13_8: type = splice_block %f32.loc13 [concrete = constants.%f32] { -// CHECK:STDOUT: %int_32.loc13: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] -// CHECK:STDOUT: %f32.loc13: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32] +// CHECK:STDOUT: %.loc6_8: type = splice_block %f32.loc6 [concrete = constants.%f32.97e] { +// CHECK:STDOUT: %int_32.loc6: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %f32.loc6: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32.97e] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc13_34.1: %f32 = value_of_initializer @__global_init.%Float32ToFloat32.call.loc13 -// CHECK:STDOUT: %.loc13_34.2: %f32 = converted @__global_init.%Float32ToFloat32.call.loc13, %.loc13_34.1 -// CHECK:STDOUT: %a: %f32 = bind_name a, %.loc13_34.2 +// CHECK:STDOUT: %.loc6_34.1: %f32.97e = value_of_initializer @__global_init.%Float32ToFloat32.call.loc6 [concrete = constants.%float.4db] +// CHECK:STDOUT: %.loc6_34.2: %f32.97e = converted @__global_init.%Float32ToFloat32.call.loc6, %.loc6_34.1 [concrete = constants.%float.4db] +// CHECK:STDOUT: %a: %f32.97e = bind_name a, %.loc6_34.2 // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %b.patt: %pattern_type.201 = binding_pattern b [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc14_8: type = splice_block %f32.loc14 [concrete = constants.%f32] { -// CHECK:STDOUT: %int_32.loc14: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] -// CHECK:STDOUT: %f32.loc14: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32] +// CHECK:STDOUT: %.loc7_8: type = splice_block %f32.loc7 [concrete = constants.%f32.97e] { +// CHECK:STDOUT: %int_32.loc7: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %f32.loc7: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32.97e] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc14_34.1: %f32 = value_of_initializer @__global_init.%Float32ToFloat32.call.loc14 -// CHECK:STDOUT: %.loc14_34.2: %f32 = converted @__global_init.%Float32ToFloat32.call.loc14, %.loc14_34.1 -// CHECK:STDOUT: %b: %f32 = bind_name b, %.loc14_34.2 +// CHECK:STDOUT: %.loc7_34.1: %f32.97e = value_of_initializer @__global_init.%Float32ToFloat32.call.loc7 [concrete = constants.%float.e3b] +// CHECK:STDOUT: %.loc7_34.2: %f32.97e = converted @__global_init.%Float32ToFloat32.call.loc7, %.loc7_34.1 [concrete = constants.%float.e3b] +// CHECK:STDOUT: %b: %f32.97e = bind_name b, %.loc7_34.2 // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %c.patt: %pattern_type.201 = binding_pattern c [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc15_8: type = splice_block %f32.loc15 [concrete = constants.%f32] { -// CHECK:STDOUT: %int_32.loc15: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] -// CHECK:STDOUT: %f32.loc15: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32] +// CHECK:STDOUT: %.loc8_8: type = splice_block %f32.loc8 [concrete = constants.%f32.97e] { +// CHECK:STDOUT: %int_32.loc8: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %f32.loc8: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32.97e] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc15_37.1: %f32 = value_of_initializer @__global_init.%Float32ToFloat32.call.loc15 -// CHECK:STDOUT: %.loc15_37.2: %f32 = converted @__global_init.%Float32ToFloat32.call.loc15, %.loc15_37.1 -// CHECK:STDOUT: %c: %f32 = bind_name c, %.loc15_37.2 +// CHECK:STDOUT: %.loc8_37.1: %f32.97e = value_of_initializer @__global_init.%Float32ToFloat32.call.loc8 [concrete = constants.%float.520] +// CHECK:STDOUT: %.loc8_37.2: %f32.97e = converted @__global_init.%Float32ToFloat32.call.loc8, %.loc8_37.1 [concrete = constants.%float.520] +// CHECK:STDOUT: %c: %f32.97e = bind_name c, %.loc8_37.2 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %Float32ToFloat32.ref.loc13: %Float32ToFloat32.type = name_ref Float32ToFloat32, imports.%Main.Float32ToFloat32 [concrete = constants.%Float32ToFloat32] -// CHECK:STDOUT: %float.loc13: Core.FloatLiteral = float_literal_value 0e-1 [concrete = constants.%float.1f7] -// CHECK:STDOUT: %impl.elem0.loc13: %.a5d = impl_witness_access constants.%ImplicitAs.impl_witness.e3f, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3] -// CHECK:STDOUT: %bound_method.loc13_31.1: = bound_method %float.loc13, %impl.elem0.loc13 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.b37] -// CHECK:STDOUT: %specific_fn.loc13: = specific_function %impl.elem0.loc13, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn] -// CHECK:STDOUT: %bound_method.loc13_31.2: = bound_method %float.loc13, %specific_fn.loc13 [concrete = constants.%bound_method.91e] -// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc13: init %f32 = call %bound_method.loc13_31.2(%float.loc13) [concrete = constants.%float.540] -// CHECK:STDOUT: %.loc13_31.1: %f32 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc13 [concrete = constants.%float.540] -// CHECK:STDOUT: %.loc13_31.2: %f32 = converted %float.loc13, %.loc13_31.1 [concrete = constants.%float.540] -// CHECK:STDOUT: %Float32ToFloat32.call.loc13: init %f32 = call %Float32ToFloat32.ref.loc13(%.loc13_31.2) -// CHECK:STDOUT: %Float32ToFloat32.ref.loc14: %Float32ToFloat32.type = name_ref Float32ToFloat32, imports.%Main.Float32ToFloat32 [concrete = constants.%Float32ToFloat32] -// CHECK:STDOUT: %float.loc14: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float.674] -// CHECK:STDOUT: %impl.elem0.loc14: %.a5d = impl_witness_access constants.%ImplicitAs.impl_witness.e3f, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3] -// CHECK:STDOUT: %bound_method.loc14_31.1: = bound_method %float.loc14, %impl.elem0.loc14 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.6d0] -// CHECK:STDOUT: %specific_fn.loc14: = specific_function %impl.elem0.loc14, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn] -// CHECK:STDOUT: %bound_method.loc14_31.2: = bound_method %float.loc14, %specific_fn.loc14 [concrete = constants.%bound_method.6b4] -// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc14: init %f32 = call %bound_method.loc14_31.2(%float.loc14) [concrete = constants.%float.3b9] -// CHECK:STDOUT: %.loc14_31.1: %f32 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc14 [concrete = constants.%float.3b9] -// CHECK:STDOUT: %.loc14_31.2: %f32 = converted %float.loc14, %.loc14_31.1 [concrete = constants.%float.3b9] -// CHECK:STDOUT: %Float32ToFloat32.call.loc14: init %f32 = call %Float32ToFloat32.ref.loc14(%.loc14_31.2) -// CHECK:STDOUT: %Float32ToFloat32.ref.loc15: %Float32ToFloat32.type = name_ref Float32ToFloat32, imports.%Main.Float32ToFloat32 [concrete = constants.%Float32ToFloat32] -// CHECK:STDOUT: %float.loc15: Core.FloatLiteral = float_literal_value 10e37 [concrete = constants.%float.516] -// CHECK:STDOUT: %impl.elem0.loc15: %.a5d = impl_witness_access constants.%ImplicitAs.impl_witness.e3f, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3] -// CHECK:STDOUT: %bound_method.loc15_31.1: = bound_method %float.loc15, %impl.elem0.loc15 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.dc9] -// CHECK:STDOUT: %specific_fn.loc15: = specific_function %impl.elem0.loc15, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn] -// CHECK:STDOUT: %bound_method.loc15_31.2: = bound_method %float.loc15, %specific_fn.loc15 [concrete = constants.%bound_method.3b8] -// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc15: init %f32 = call %bound_method.loc15_31.2(%float.loc15) [concrete = constants.%float.a77] -// CHECK:STDOUT: %.loc15_31.1: %f32 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc15 [concrete = constants.%float.a77] -// CHECK:STDOUT: %.loc15_31.2: %f32 = converted %float.loc15, %.loc15_31.1 [concrete = constants.%float.a77] -// CHECK:STDOUT: %Float32ToFloat32.call.loc15: init %f32 = call %Float32ToFloat32.ref.loc15(%.loc15_31.2) +// CHECK:STDOUT: %Float32ToFloat32.ref.loc6: %Float32ToFloat32.type = name_ref Float32ToFloat32, imports.%Main.Float32ToFloat32 [concrete = constants.%Float32ToFloat32] +// CHECK:STDOUT: %float.loc6: Core.FloatLiteral = float_literal_value 0e-1 [concrete = constants.%float.1f7] +// CHECK:STDOUT: %impl.elem0.loc6: %.a5d = impl_witness_access constants.%ImplicitAs.impl_witness.e3f, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3] +// CHECK:STDOUT: %bound_method.loc6_31.1: = bound_method %float.loc6, %impl.elem0.loc6 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.b37] +// CHECK:STDOUT: %specific_fn.loc6: = specific_function %impl.elem0.loc6, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc6_31.2: = bound_method %float.loc6, %specific_fn.loc6 [concrete = constants.%bound_method.91e] +// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6: init %f32.97e = call %bound_method.loc6_31.2(%float.loc6) [concrete = constants.%float.4db] +// CHECK:STDOUT: %.loc6_31.1: %f32.97e = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6 [concrete = constants.%float.4db] +// CHECK:STDOUT: %.loc6_31.2: %f32.97e = converted %float.loc6, %.loc6_31.1 [concrete = constants.%float.4db] +// CHECK:STDOUT: %Float32ToFloat32.call.loc6: init %f32.97e = call %Float32ToFloat32.ref.loc6(%.loc6_31.2) [concrete = constants.%float.4db] +// CHECK:STDOUT: %Float32ToFloat32.ref.loc7: %Float32ToFloat32.type = name_ref Float32ToFloat32, imports.%Main.Float32ToFloat32 [concrete = constants.%Float32ToFloat32] +// CHECK:STDOUT: %float.loc7: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float.674] +// CHECK:STDOUT: %impl.elem0.loc7: %.a5d = impl_witness_access constants.%ImplicitAs.impl_witness.e3f, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3] +// CHECK:STDOUT: %bound_method.loc7_31.1: = bound_method %float.loc7, %impl.elem0.loc7 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.6d0] +// CHECK:STDOUT: %specific_fn.loc7: = specific_function %impl.elem0.loc7, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc7_31.2: = bound_method %float.loc7, %specific_fn.loc7 [concrete = constants.%bound_method.6b4] +// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7: init %f32.97e = call %bound_method.loc7_31.2(%float.loc7) [concrete = constants.%float.e3b] +// CHECK:STDOUT: %.loc7_31.1: %f32.97e = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7 [concrete = constants.%float.e3b] +// CHECK:STDOUT: %.loc7_31.2: %f32.97e = converted %float.loc7, %.loc7_31.1 [concrete = constants.%float.e3b] +// CHECK:STDOUT: %Float32ToFloat32.call.loc7: init %f32.97e = call %Float32ToFloat32.ref.loc7(%.loc7_31.2) [concrete = constants.%float.e3b] +// CHECK:STDOUT: %Float32ToFloat32.ref.loc8: %Float32ToFloat32.type = name_ref Float32ToFloat32, imports.%Main.Float32ToFloat32 [concrete = constants.%Float32ToFloat32] +// CHECK:STDOUT: %float.loc8: Core.FloatLiteral = float_literal_value 10e37 [concrete = constants.%float.516] +// CHECK:STDOUT: %impl.elem0.loc8: %.a5d = impl_witness_access constants.%ImplicitAs.impl_witness.e3f, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3] +// CHECK:STDOUT: %bound_method.loc8_31.1: = bound_method %float.loc8, %impl.elem0.loc8 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.dc9] +// CHECK:STDOUT: %specific_fn.loc8: = specific_function %impl.elem0.loc8, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc8_31.2: = bound_method %float.loc8, %specific_fn.loc8 [concrete = constants.%bound_method.3b8] +// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc8: init %f32.97e = call %bound_method.loc8_31.2(%float.loc8) [concrete = constants.%float.520] +// CHECK:STDOUT: %.loc8_31.1: %f32.97e = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc8 [concrete = constants.%float.520] +// CHECK:STDOUT: %.loc8_31.2: %f32.97e = converted %float.loc8, %.loc8_31.1 [concrete = constants.%float.520] +// CHECK:STDOUT: %Float32ToFloat32.call.loc8: init %f32.97e = call %Float32ToFloat32.ref.loc8(%.loc8_31.2) [concrete = constants.%float.520] // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_truncate.carbon +// CHECK:STDOUT: --- truncate.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] -// CHECK:STDOUT: %f32: type = class_type @Float, @Float(%int_32) [concrete] -// CHECK:STDOUT: %pattern_type.201: type = pattern_type %f32 [concrete] +// CHECK:STDOUT: %f32.97e: type = class_type @Float, @Float(%int_32) [concrete] +// CHECK:STDOUT: %pattern_type.201: type = pattern_type %f32.97e [concrete] // CHECK:STDOUT: %Float64ToFloat32.type: type = fn_type @Float64ToFloat32 [concrete] // CHECK:STDOUT: %Float64ToFloat32: %Float64ToFloat32.type = struct_value () [concrete] // CHECK:STDOUT: %int_64: Core.IntLiteral = int_value 64 [concrete] @@ -612,6 +566,7 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64); // CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete] // CHECK:STDOUT: %bound_method: = bound_method %float.674, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] // CHECK:STDOUT: %float.d20: %f64.d77 = float_value 1 [concrete] +// CHECK:STDOUT: %float.e3b: %f32.97e = float_value 1 [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -624,13 +579,13 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64); // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %a.patt: %pattern_type.201 = binding_pattern a [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc13_8: type = splice_block %f32 [concrete = constants.%f32] { +// CHECK:STDOUT: %.loc6_8: type = splice_block %f32 [concrete = constants.%f32.97e] { // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] -// CHECK:STDOUT: %f32: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32] +// CHECK:STDOUT: %f32: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32.97e] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc13_34.1: %f32 = value_of_initializer @__global_init.%Float64ToFloat32.call -// CHECK:STDOUT: %.loc13_34.2: %f32 = converted @__global_init.%Float64ToFloat32.call, %.loc13_34.1 -// CHECK:STDOUT: %a: %f32 = bind_name a, %.loc13_34.2 +// CHECK:STDOUT: %.loc6_34.1: %f32.97e = value_of_initializer @__global_init.%Float64ToFloat32.call [concrete = constants.%float.e3b] +// CHECK:STDOUT: %.loc6_34.2: %f32.97e = converted @__global_init.%Float64ToFloat32.call, %.loc6_34.1 [concrete = constants.%float.e3b] +// CHECK:STDOUT: %a: %f32.97e = bind_name a, %.loc6_34.2 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { @@ -638,13 +593,13 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64); // CHECK:STDOUT: %Float64ToFloat32.ref: %Float64ToFloat32.type = name_ref Float64ToFloat32, imports.%Main.Float64ToFloat32 [concrete = constants.%Float64ToFloat32] // CHECK:STDOUT: %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float.674] // CHECK:STDOUT: %impl.elem0: %.678 = impl_witness_access constants.%ImplicitAs.impl_witness.857, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03] -// CHECK:STDOUT: %bound_method.loc13_31.1: = bound_method %float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %bound_method.loc6_31.1: = bound_method %float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound] // CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn] -// CHECK:STDOUT: %bound_method.loc13_31.2: = bound_method %float, %specific_fn [concrete = constants.%bound_method] -// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f64.d77 = call %bound_method.loc13_31.2(%float) [concrete = constants.%float.d20] -// CHECK:STDOUT: %.loc13_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float.d20] -// CHECK:STDOUT: %.loc13_31.2: %f64.d77 = converted %float, %.loc13_31.1 [concrete = constants.%float.d20] -// CHECK:STDOUT: %Float64ToFloat32.call: init %f32 = call %Float64ToFloat32.ref(%.loc13_31.2) +// CHECK:STDOUT: %bound_method.loc6_31.2: = bound_method %float, %specific_fn [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f64.d77 = call %bound_method.loc6_31.2(%float) [concrete = constants.%float.d20] +// CHECK:STDOUT: %.loc6_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float.d20] +// CHECK:STDOUT: %.loc6_31.2: %f64.d77 = converted %float, %.loc6_31.1 [concrete = constants.%float.d20] +// CHECK:STDOUT: %Float64ToFloat32.call: init %f32.97e = call %Float64ToFloat32.ref(%.loc6_31.2) [concrete = constants.%float.e3b] // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: @@ -652,8 +607,8 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64); // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] -// CHECK:STDOUT: %f32: type = class_type @Float, @Float(%int_32) [concrete] -// CHECK:STDOUT: %pattern_type.201: type = pattern_type %f32 [concrete] +// CHECK:STDOUT: %f32.97e: type = class_type @Float, @Float(%int_32) [concrete] +// CHECK:STDOUT: %pattern_type.201: type = pattern_type %f32.97e [concrete] // CHECK:STDOUT: %Float64ToFloat32.type: type = fn_type @Float64ToFloat32 [concrete] // CHECK:STDOUT: %Float64ToFloat32: %Float64ToFloat32.type = struct_value () [concrete] // CHECK:STDOUT: %int_64: Core.IntLiteral = int_value 64 [concrete] @@ -694,53 +649,53 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64); // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %a.patt: %pattern_type.201 = binding_pattern a [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc16_8: type = splice_block %f32.loc16 [concrete = constants.%f32] { -// CHECK:STDOUT: %int_32.loc16: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] -// CHECK:STDOUT: %f32.loc16: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32] +// CHECK:STDOUT: %.loc11_8: type = splice_block %f32.loc11 [concrete = constants.%f32.97e] { +// CHECK:STDOUT: %int_32.loc11: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %f32.loc11: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32.97e] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc16_37.1: %f32 = value_of_initializer @__global_init.%Float64ToFloat32.call -// CHECK:STDOUT: %.loc16_37.2: %f32 = converted @__global_init.%Float64ToFloat32.call, %.loc16_37.1 -// CHECK:STDOUT: %a: %f32 = bind_name a, %.loc16_37.2 +// CHECK:STDOUT: %.loc11_37.1: %f32.97e = value_of_initializer @__global_init.%Float64ToFloat32.call [concrete = ] +// CHECK:STDOUT: %.loc11_37.2: %f32.97e = converted @__global_init.%Float64ToFloat32.call, %.loc11_37.1 [concrete = ] +// CHECK:STDOUT: %a: %f32.97e = bind_name a, %.loc11_37.2 [concrete = ] // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %b.patt: %pattern_type.201 = binding_pattern b [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc17_8: type = splice_block %f32.loc17 [concrete = constants.%f32] { -// CHECK:STDOUT: %int_32.loc17: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] -// CHECK:STDOUT: %f32.loc17: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32] +// CHECK:STDOUT: %.loc16_8: type = splice_block %f32.loc16 [concrete = constants.%f32.97e] { +// CHECK:STDOUT: %int_32.loc16: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %f32.loc16: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32.97e] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc17_42.1: %f32 = value_of_initializer @__global_init.%FloatLiteralToFloat32.call -// CHECK:STDOUT: %.loc17_42.2: %f32 = converted @__global_init.%FloatLiteralToFloat32.call, %.loc17_42.1 -// CHECK:STDOUT: %b: %f32 = bind_name b, %.loc17_42.2 +// CHECK:STDOUT: %.loc16_42.1: %f32.97e = value_of_initializer @__global_init.%FloatLiteralToFloat32.call [concrete = ] +// CHECK:STDOUT: %.loc16_42.2: %f32.97e = converted @__global_init.%FloatLiteralToFloat32.call, %.loc16_42.1 [concrete = ] +// CHECK:STDOUT: %b: %f32.97e = bind_name b, %.loc16_42.2 [concrete = ] // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %c.patt: %pattern_type.0ae = binding_pattern c [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc22_8: type = splice_block %f64 [concrete = constants.%f64.d77] { +// CHECK:STDOUT: %.loc21_8: type = splice_block %f64 [concrete = constants.%f64.d77] { // CHECK:STDOUT: %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64] // CHECK:STDOUT: %f64: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc22_43.1: %f64.d77 = value_of_initializer @__global_init.%FloatLiteralToFloat64.call [concrete = ] -// CHECK:STDOUT: %.loc22_43.2: %f64.d77 = converted @__global_init.%FloatLiteralToFloat64.call, %.loc22_43.1 [concrete = ] -// CHECK:STDOUT: %c: %f64.d77 = bind_name c, %.loc22_43.2 [concrete = ] +// CHECK:STDOUT: %.loc21_43.1: %f64.d77 = value_of_initializer @__global_init.%FloatLiteralToFloat64.call [concrete = ] +// CHECK:STDOUT: %.loc21_43.2: %f64.d77 = converted @__global_init.%FloatLiteralToFloat64.call, %.loc21_43.1 [concrete = ] +// CHECK:STDOUT: %c: %f64.d77 = bind_name c, %.loc21_43.2 [concrete = ] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %Float64ToFloat32.ref: %Float64ToFloat32.type = name_ref Float64ToFloat32, imports.%Main.Float64ToFloat32 [concrete = constants.%Float64ToFloat32] -// CHECK:STDOUT: %float.loc16: Core.FloatLiteral = float_literal_value 10e38 [concrete = constants.%float.bfd691.1] +// CHECK:STDOUT: %float.loc11: Core.FloatLiteral = float_literal_value 10e38 [concrete = constants.%float.bfd691.1] // CHECK:STDOUT: %impl.elem0: %.678 = impl_witness_access constants.%ImplicitAs.impl_witness.857, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03] -// CHECK:STDOUT: %bound_method.loc16_31.1: = bound_method %float.loc16, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %bound_method.loc11_31.1: = bound_method %float.loc11, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound] // CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn] -// CHECK:STDOUT: %bound_method.loc16_31.2: = bound_method %float.loc16, %specific_fn [concrete = constants.%bound_method] -// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f64.d77 = call %bound_method.loc16_31.2(%float.loc16) [concrete = constants.%float.c37] -// CHECK:STDOUT: %.loc16_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float.c37] -// CHECK:STDOUT: %.loc16_31.2: %f64.d77 = converted %float.loc16, %.loc16_31.1 [concrete = constants.%float.c37] -// CHECK:STDOUT: %Float64ToFloat32.call: init %f32 = call %Float64ToFloat32.ref(%.loc16_31.2) +// CHECK:STDOUT: %bound_method.loc11_31.2: = bound_method %float.loc11, %specific_fn [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f64.d77 = call %bound_method.loc11_31.2(%float.loc11) [concrete = constants.%float.c37] +// CHECK:STDOUT: %.loc11_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float.c37] +// CHECK:STDOUT: %.loc11_31.2: %f64.d77 = converted %float.loc11, %.loc11_31.1 [concrete = constants.%float.c37] +// CHECK:STDOUT: %Float64ToFloat32.call: init %f32.97e = call %Float64ToFloat32.ref(%.loc11_31.2) [concrete = ] // CHECK:STDOUT: %FloatLiteralToFloat32.ref: %FloatLiteralToFloat32.type = name_ref FloatLiteralToFloat32, imports.%Main.FloatLiteralToFloat32 [concrete = constants.%FloatLiteralToFloat32] -// CHECK:STDOUT: %float.loc17: Core.FloatLiteral = float_literal_value 10e38 [concrete = constants.%float.bfd691.2] -// CHECK:STDOUT: %FloatLiteralToFloat32.call: init %f32 = call %FloatLiteralToFloat32.ref(%float.loc17) +// CHECK:STDOUT: %float.loc16: Core.FloatLiteral = float_literal_value 10e38 [concrete = constants.%float.bfd691.2] +// CHECK:STDOUT: %FloatLiteralToFloat32.call: init %f32.97e = call %FloatLiteralToFloat32.ref(%float.loc16) [concrete = ] // CHECK:STDOUT: %FloatLiteralToFloat64.ref: %FloatLiteralToFloat64.type = name_ref FloatLiteralToFloat64, imports.%Main.FloatLiteralToFloat64 [concrete = constants.%FloatLiteralToFloat64] -// CHECK:STDOUT: %float.loc22: Core.FloatLiteral = float_literal_value 10e308 [concrete = constants.%float.bb5] -// CHECK:STDOUT: %FloatLiteralToFloat64.call: init %f64.d77 = call %FloatLiteralToFloat64.ref(%float.loc22) [concrete = ] +// CHECK:STDOUT: %float.loc21: Core.FloatLiteral = float_literal_value 10e308 [concrete = constants.%float.bb5] +// CHECK:STDOUT: %FloatLiteralToFloat64.call: init %f64.d77 = call %FloatLiteralToFloat64.ref(%float.loc21) [concrete = ] // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: @@ -753,10 +708,10 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64); // CHECK:STDOUT: %Float32ToFloat64.type: type = fn_type @Float32ToFloat64 [concrete] // CHECK:STDOUT: %Float32ToFloat64: %Float32ToFloat64.type = struct_value () [concrete] // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] -// CHECK:STDOUT: %f32: type = class_type @Float, @Float(%int_32) [concrete] +// CHECK:STDOUT: %f32.97e: type = class_type @Float, @Float(%int_32) [concrete] // CHECK:STDOUT: %float.674: Core.FloatLiteral = float_literal_value 10e-1 [concrete] -// CHECK:STDOUT: %ImplicitAs.type.31d: type = facet_type <@ImplicitAs, @ImplicitAs(%f32)> [concrete] -// CHECK:STDOUT: %ImplicitAs.Convert.type.b8c: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f32) [concrete] +// CHECK:STDOUT: %ImplicitAs.type.31d: type = facet_type <@ImplicitAs, @ImplicitAs(%f32.97e)> [concrete] +// CHECK:STDOUT: %ImplicitAs.Convert.type.b8c: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f32.97e) [concrete] // CHECK:STDOUT: %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic] // CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic] // CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.b45: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.644 = struct_value () [symbolic] @@ -768,11 +723,13 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64); // CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.6d0: = bound_method %float.674, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete] // CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] // CHECK:STDOUT: %bound_method.6b4: = bound_method %float.674, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] -// CHECK:STDOUT: %float.3b9: %f32 = float_value 1 [concrete] +// CHECK:STDOUT: %float.e3b: %f32.97e = float_value 1 [concrete] +// CHECK:STDOUT: %float.d20: %f64.d77 = float_value 1 [concrete] // CHECK:STDOUT: %float.9bd: Core.FloatLiteral = float_literal_value 10e29 [concrete] // CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.a5c: = bound_method %float.9bd, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete] // CHECK:STDOUT: %bound_method.3e4: = bound_method %float.9bd, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] -// CHECK:STDOUT: %float.82f: %f32 = float_value 1.0E+30 [concrete] +// CHECK:STDOUT: %float.7d4: %f32.97e = float_value 1.00000002E+30 [concrete] +// CHECK:STDOUT: %float.6a7: %f64.d77 = float_value 1.0000000150474662E+30 [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -789,8 +746,8 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64); // CHECK:STDOUT: %int_64.loc6: Core.IntLiteral = int_value 64 [concrete = constants.%int_64] // CHECK:STDOUT: %f64.loc6: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc6_34.1: %f64.d77 = value_of_initializer @__global_init.%Float32ToFloat64.call.loc6 -// CHECK:STDOUT: %.loc6_34.2: %f64.d77 = converted @__global_init.%Float32ToFloat64.call.loc6, %.loc6_34.1 +// CHECK:STDOUT: %.loc6_34.1: %f64.d77 = value_of_initializer @__global_init.%Float32ToFloat64.call.loc6 [concrete = constants.%float.d20] +// CHECK:STDOUT: %.loc6_34.2: %f64.d77 = converted @__global_init.%Float32ToFloat64.call.loc6, %.loc6_34.1 [concrete = constants.%float.d20] // CHECK:STDOUT: %a: %f64.d77 = bind_name a, %.loc6_34.2 // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %b.patt: %pattern_type.0ae = binding_pattern b [concrete] @@ -799,8 +756,8 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64); // CHECK:STDOUT: %int_64.loc7: Core.IntLiteral = int_value 64 [concrete = constants.%int_64] // CHECK:STDOUT: %f64.loc7: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc7_37.1: %f64.d77 = value_of_initializer @__global_init.%Float32ToFloat64.call.loc7 -// CHECK:STDOUT: %.loc7_37.2: %f64.d77 = converted @__global_init.%Float32ToFloat64.call.loc7, %.loc7_37.1 +// CHECK:STDOUT: %.loc7_37.1: %f64.d77 = value_of_initializer @__global_init.%Float32ToFloat64.call.loc7 [concrete = constants.%float.6a7] +// CHECK:STDOUT: %.loc7_37.2: %f64.d77 = converted @__global_init.%Float32ToFloat64.call.loc7, %.loc7_37.1 [concrete = constants.%float.6a7] // CHECK:STDOUT: %b: %f64.d77 = bind_name b, %.loc7_37.2 // CHECK:STDOUT: } // CHECK:STDOUT: @@ -812,20 +769,20 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64); // CHECK:STDOUT: %bound_method.loc6_31.1: = bound_method %float.loc6, %impl.elem0.loc6 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.6d0] // CHECK:STDOUT: %specific_fn.loc6: = specific_function %impl.elem0.loc6, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn] // CHECK:STDOUT: %bound_method.loc6_31.2: = bound_method %float.loc6, %specific_fn.loc6 [concrete = constants.%bound_method.6b4] -// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6: init %f32 = call %bound_method.loc6_31.2(%float.loc6) [concrete = constants.%float.3b9] -// CHECK:STDOUT: %.loc6_31.1: %f32 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6 [concrete = constants.%float.3b9] -// CHECK:STDOUT: %.loc6_31.2: %f32 = converted %float.loc6, %.loc6_31.1 [concrete = constants.%float.3b9] -// CHECK:STDOUT: %Float32ToFloat64.call.loc6: init %f64.d77 = call %Float32ToFloat64.ref.loc6(%.loc6_31.2) +// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6: init %f32.97e = call %bound_method.loc6_31.2(%float.loc6) [concrete = constants.%float.e3b] +// CHECK:STDOUT: %.loc6_31.1: %f32.97e = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6 [concrete = constants.%float.e3b] +// CHECK:STDOUT: %.loc6_31.2: %f32.97e = converted %float.loc6, %.loc6_31.1 [concrete = constants.%float.e3b] +// CHECK:STDOUT: %Float32ToFloat64.call.loc6: init %f64.d77 = call %Float32ToFloat64.ref.loc6(%.loc6_31.2) [concrete = constants.%float.d20] // CHECK:STDOUT: %Float32ToFloat64.ref.loc7: %Float32ToFloat64.type = name_ref Float32ToFloat64, imports.%Main.Float32ToFloat64 [concrete = constants.%Float32ToFloat64] // CHECK:STDOUT: %float.loc7: Core.FloatLiteral = float_literal_value 10e29 [concrete = constants.%float.9bd] // CHECK:STDOUT: %impl.elem0.loc7: %.a5d = impl_witness_access constants.%ImplicitAs.impl_witness.e3f, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3] // CHECK:STDOUT: %bound_method.loc7_31.1: = bound_method %float.loc7, %impl.elem0.loc7 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.a5c] // CHECK:STDOUT: %specific_fn.loc7: = specific_function %impl.elem0.loc7, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn] // CHECK:STDOUT: %bound_method.loc7_31.2: = bound_method %float.loc7, %specific_fn.loc7 [concrete = constants.%bound_method.3e4] -// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7: init %f32 = call %bound_method.loc7_31.2(%float.loc7) [concrete = constants.%float.82f] -// CHECK:STDOUT: %.loc7_31.1: %f32 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7 [concrete = constants.%float.82f] -// CHECK:STDOUT: %.loc7_31.2: %f32 = converted %float.loc7, %.loc7_31.1 [concrete = constants.%float.82f] -// CHECK:STDOUT: %Float32ToFloat64.call.loc7: init %f64.d77 = call %Float32ToFloat64.ref.loc7(%.loc7_31.2) +// CHECK:STDOUT: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7: init %f32.97e = call %bound_method.loc7_31.2(%float.loc7) [concrete = constants.%float.7d4] +// CHECK:STDOUT: %.loc7_31.1: %f32.97e = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7 [concrete = constants.%float.7d4] +// CHECK:STDOUT: %.loc7_31.2: %f32.97e = converted %float.loc7, %.loc7_31.1 [concrete = constants.%float.7d4] +// CHECK:STDOUT: %Float32ToFloat64.call.loc7: init %f64.d77 = call %Float32ToFloat64.ref.loc7(%.loc7_31.2) [concrete = constants.%float.6a7] // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/builtins/float/div_assign.carbon b/toolchain/check/testdata/builtins/float/div_assign.carbon index 6cbf6dd3ff55..530156731d1b 100644 --- a/toolchain/check/testdata/builtins/float/div_assign.carbon +++ b/toolchain/check/testdata/builtins/float/div_assign.carbon @@ -30,13 +30,6 @@ library "[[@TEST_NAME]]"; // CHECK:STDERR: fn NotPtr(a: f64, b: f64) = "float.div_assign"; -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] -// CHECK:STDERR: adapt MakeFloat(N); -// CHECK:STDERR: ^~~~~~~~~~~~ -// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+8]]:24: note: in `f32` used here [ResolvingSpecificHere] -// CHECK:STDERR: fn MixedTypes(a: f64*, b: f32) = "float.div_assign"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: // CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.div_assign" [InvalidBuiltinSignature] // CHECK:STDERR: fn MixedTypes(a: f64*, b: f32) = "float.div_assign"; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/toolchain/check/testdata/builtins/float/make_type.carbon b/toolchain/check/testdata/builtins/float/make_type.carbon index f8db3021877e..226f935cb24d 100644 --- a/toolchain/check/testdata/builtins/float/make_type.carbon +++ b/toolchain/check/testdata/builtins/float/make_type.carbon @@ -22,7 +22,10 @@ library "[[@TEST_NAME]]"; import library "types"; -var f: Float(64); +var a: Float(16); +var b: Float(32); +var c: Float(64); +var d: Float(128); fn GetFloat(dyn_size: i32) -> type { //@dump-sem-ir-begin @@ -36,7 +39,7 @@ library "[[@TEST_NAME]]"; import library "types"; -// CHECK:STDERR: fail_invalid_size.carbon:[[@LINE+4]]:20: error: bit width must be 64 [CompileTimeFloatBitWidth] +// CHECK:STDERR: fail_invalid_size.carbon:[[@LINE+4]]:20: error: unsupported floating-point bit width 931 [CompileTimeFloatBitWidth] // CHECK:STDERR: var invalid_float: Float(931); // CHECK:STDERR: ^~~~~~~~~~ // CHECK:STDERR: @@ -60,8 +63,8 @@ var dyn: Float(dyn_size); // CHECK:STDOUT: constants { // CHECK:STDOUT: %Float.type: type = fn_type @Float [concrete] // CHECK:STDOUT: %Float: %Float.type = struct_value () [concrete] -// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] -// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %int_32.be0: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32.be0) [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -73,8 +76,8 @@ var dyn: Float(dyn_size); // CHECK:STDOUT: %Float.ref: %Float.type = name_ref Float, imports.%Main.Float [concrete = constants.%Float] // CHECK:STDOUT: %dyn_size.ref: %i32 = name_ref dyn_size, %dyn_size // CHECK:STDOUT: %Float.call: init type = call %Float.ref(%dyn_size.ref) -// CHECK:STDOUT: %.loc10_25.1: type = value_of_initializer %Float.call -// CHECK:STDOUT: %.loc10_25.2: type = converted %Float.call, %.loc10_25.1 -// CHECK:STDOUT: return %.loc10_25.2 +// CHECK:STDOUT: %.loc13_25.1: type = value_of_initializer %Float.call +// CHECK:STDOUT: %.loc13_25.2: type = converted %Float.call, %.loc13_25.1 +// CHECK:STDOUT: return %.loc13_25.2 // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/builtins/float/mul_assign.carbon b/toolchain/check/testdata/builtins/float/mul_assign.carbon index 43dfa6a69132..ff2c3894a677 100644 --- a/toolchain/check/testdata/builtins/float/mul_assign.carbon +++ b/toolchain/check/testdata/builtins/float/mul_assign.carbon @@ -30,13 +30,6 @@ library "[[@TEST_NAME]]"; // CHECK:STDERR: fn NotPtr(a: f64, b: f64) = "float.mul_assign"; -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] -// CHECK:STDERR: adapt MakeFloat(N); -// CHECK:STDERR: ^~~~~~~~~~~~ -// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+8]]:24: note: in `f32` used here [ResolvingSpecificHere] -// CHECK:STDERR: fn MixedTypes(a: f64*, b: f32) = "float.mul_assign"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: // CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.mul_assign" [InvalidBuiltinSignature] // CHECK:STDERR: fn MixedTypes(a: f64*, b: f32) = "float.mul_assign"; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/toolchain/check/testdata/builtins/float/sub_assign.carbon b/toolchain/check/testdata/builtins/float/sub_assign.carbon index 35d368b4666f..aa579add197d 100644 --- a/toolchain/check/testdata/builtins/float/sub_assign.carbon +++ b/toolchain/check/testdata/builtins/float/sub_assign.carbon @@ -30,13 +30,6 @@ library "[[@TEST_NAME]]"; // CHECK:STDERR: fn NotPtr(a: f64, b: f64) = "float.sub_assign"; -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] -// CHECK:STDERR: adapt MakeFloat(N); -// CHECK:STDERR: ^~~~~~~~~~~~ -// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+8]]:24: note: in `f32` used here [ResolvingSpecificHere] -// CHECK:STDERR: fn MixedTypes(a: f64*, b: f32) = "float.sub_assign"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: // CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.sub_assign" [InvalidBuiltinSignature] // CHECK:STDERR: fn MixedTypes(a: f64*, b: f32) = "float.sub_assign"; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/toolchain/check/testdata/deduce/int_float.carbon b/toolchain/check/testdata/deduce/int_float.carbon index 36772e75a719..43390e298882 100644 --- a/toolchain/check/testdata/deduce/int_float.carbon +++ b/toolchain/check/testdata/deduce/int_float.carbon @@ -194,8 +194,8 @@ fn G(a: f64) -> Core.IntLiteral() { // CHECK:STDOUT: %pattern_type.0ae: type = pattern_type %f64.d77 [concrete] // CHECK:STDOUT: %G.type: type = fn_type @G [concrete] // CHECK:STDOUT: %G: %G.type = struct_value () [concrete] -// CHECK:STDOUT: %f64.cae: type = float_type %int_64 [concrete] -// CHECK:STDOUT: %complete_type.3f9: = complete_type_witness %f64.cae [concrete] +// CHECK:STDOUT: %f64.794: type = float_type %int_64, f64 [concrete] +// CHECK:STDOUT: %complete_type.7b9: = complete_type_witness %f64.794 [concrete] // CHECK:STDOUT: %F.specific_fn: = specific_function %F, @F(%int_64) [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -309,6 +309,6 @@ fn G(a: f64) -> Core.IntLiteral() { // CHECK:STDOUT: %pattern_type => constants.%pattern_type.0ae // CHECK:STDOUT: // CHECK:STDOUT: !definition: -// CHECK:STDOUT: %require_complete => constants.%complete_type.3f9 +// CHECK:STDOUT: %require_complete => constants.%complete_type.7b9 // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon b/toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon index 0d494a5c8f52..392c6cfbc1b1 100644 --- a/toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon +++ b/toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon +// EXTRA-ARGS: --target=x86_64-linux-gnu // // AUTOUPDATE // TIP: To test this file alone, run: @@ -357,6 +358,46 @@ fn F() { //@dump-sem-ir-end } +// ============================================================================ +// _Float16 param +// ============================================================================ + +// --- float16_param.h + +auto foo(_Float16 a) -> void; + +// --- import_float16_param.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "float16_param.h"; + +fn F() { + //@dump-sem-ir-begin + Cpp.foo(0.8 as f16); + //@dump-sem-ir-end +} + +// ============================================================================ +// float param +// ============================================================================ + +// --- float_param.h + +auto foo(float a) -> void; + +// --- import_float_param.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "float_param.h"; + +fn F() { + //@dump-sem-ir-begin + Cpp.foo(0.8 as f32); + //@dump-sem-ir-end +} + // ============================================================================ // double param // ============================================================================ @@ -377,6 +418,26 @@ fn F() { //@dump-sem-ir-end } +// ============================================================================ +// __float128 param +// ============================================================================ + +// --- float128_param.h + +auto foo(__float128 a) -> void; + +// --- import_float128_param.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "float128_param.h"; + +fn F() { + //@dump-sem-ir-begin + Cpp.foo(0.8 as f128); + //@dump-sem-ir-end +} + // ============================================================================ // bool return // ============================================================================ @@ -1331,6 +1392,156 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- import_float16_param.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %int_16: Core.IntLiteral = int_value 16 [concrete] +// CHECK:STDOUT: %f16.a6a: type = class_type @Float, @Float(%int_16) [concrete] +// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] +// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] +// CHECK:STDOUT: %ptr.823: type = ptr_type %f16.a6a [concrete] +// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] +// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: %float.c64: Core.FloatLiteral = float_literal_value 8e-1 [concrete] +// CHECK:STDOUT: %As.type.c58: type = facet_type <@As, @As(%f16.a6a)> [concrete] +// CHECK:STDOUT: %As.Convert.type.c23: type = fn_type @As.Convert, @As(%f16.a6a) [concrete] +// CHECK:STDOUT: %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.type.6a5: type = fn_type @Core.FloatLiteral.as.As.impl.Convert, @Core.FloatLiteral.as.As.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.6af: %Core.FloatLiteral.as.As.impl.Convert.type.6a5 = struct_value () [symbolic] +// CHECK:STDOUT: %As.impl_witness.bc0: = impl_witness imports.%As.impl_witness_table, @Core.FloatLiteral.as.As.impl(%int_16) [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.type.f15: type = fn_type @Core.FloatLiteral.as.As.impl.Convert, @Core.FloatLiteral.as.As.impl(%int_16) [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.e2a: %Core.FloatLiteral.as.As.impl.Convert.type.f15 = struct_value () [concrete] +// CHECK:STDOUT: %As.facet: %As.type.c58 = facet_value Core.FloatLiteral, (%As.impl_witness.bc0) [concrete] +// CHECK:STDOUT: %.178: type = fn_type_with_self_type %As.Convert.type.c23, %As.facet [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.bound: = bound_method %float.c64, %Core.FloatLiteral.as.As.impl.Convert.e2a [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.specific_fn: = specific_function %Core.FloatLiteral.as.As.impl.Convert.e2a, @Core.FloatLiteral.as.As.impl.Convert(%int_16) [concrete] +// CHECK:STDOUT: %bound_method: = bound_method %float.c64, %Core.FloatLiteral.as.As.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %float.032: %f16.a6a = float_value 0.7998 [concrete] +// CHECK:STDOUT: %Float.as.Destroy.impl.Op.type.cf1: type = fn_type @Float.as.Destroy.impl.Op, @Float.as.Destroy.impl(%int_16) [concrete] +// CHECK:STDOUT: %Float.as.Destroy.impl.Op.85f: %Float.as.Destroy.impl.Op.type.cf1 = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .foo = %foo.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import_ref.2c9: @Core.FloatLiteral.as.As.impl.%Core.FloatLiteral.as.As.impl.Convert.type (%Core.FloatLiteral.as.As.impl.Convert.type.6a5) = import_ref Core//prelude/parts/float, loc20_41, loaded [symbolic = @Core.FloatLiteral.as.As.impl.%Core.FloatLiteral.as.As.impl.Convert (constants.%Core.FloatLiteral.as.As.impl.Convert.6af)] +// CHECK:STDOUT: %As.impl_witness_table = impl_witness_table (%Core.import_ref.2c9), @Core.FloatLiteral.as.As.impl [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %float: Core.FloatLiteral = float_literal_value 8e-1 [concrete = constants.%float.c64] +// CHECK:STDOUT: %int_16: Core.IntLiteral = int_value 16 [concrete = constants.%int_16] +// CHECK:STDOUT: %f16: type = class_type @Float, @Float(constants.%int_16) [concrete = constants.%f16.a6a] +// CHECK:STDOUT: %impl.elem0: %.178 = impl_witness_access constants.%As.impl_witness.bc0, element0 [concrete = constants.%Core.FloatLiteral.as.As.impl.Convert.e2a] +// CHECK:STDOUT: %bound_method.loc8_15.1: = bound_method %float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.As.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @Core.FloatLiteral.as.As.impl.Convert(constants.%int_16) [concrete = constants.%Core.FloatLiteral.as.As.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc8_15.2: = bound_method %float, %specific_fn [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.call: init %f16.a6a = call %bound_method.loc8_15.2(%float) [concrete = constants.%float.032] +// CHECK:STDOUT: %.loc8_15.1: %f16.a6a = value_of_initializer %Core.FloatLiteral.as.As.impl.Convert.call [concrete = constants.%float.032] +// CHECK:STDOUT: %.loc8_15.2: %f16.a6a = converted %float, %.loc8_15.1 [concrete = constants.%float.032] +// CHECK:STDOUT: %.loc8_15.3: ref %f16.a6a = temporary_storage +// CHECK:STDOUT: %.loc8_15.4: ref %f16.a6a = temporary %.loc8_15.3, %.loc8_15.2 +// CHECK:STDOUT: %addr.loc8_21: %ptr.823 = addr_of %.loc8_15.4 +// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_21) +// CHECK:STDOUT: %Float.as.Destroy.impl.Op.bound: = bound_method %.loc8_15.3, constants.%Float.as.Destroy.impl.Op.85f +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method.loc8_15.3: = bound_method %.loc8_15.3, %Float.as.Destroy.impl.Op.specific_fn +// CHECK:STDOUT: %addr.loc8_15: %ptr.823 = addr_of %.loc8_15.3 +// CHECK:STDOUT: %Float.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method.loc8_15.3(%addr.loc8_15) +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- import_float_param.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %f32.97e: type = class_type @Float, @Float(%int_32) [concrete] +// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] +// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] +// CHECK:STDOUT: %ptr.0bc: type = ptr_type %f32.97e [concrete] +// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] +// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: %float.c64: Core.FloatLiteral = float_literal_value 8e-1 [concrete] +// CHECK:STDOUT: %As.type.114: type = facet_type <@As, @As(%f32.97e)> [concrete] +// CHECK:STDOUT: %As.Convert.type.f5e: type = fn_type @As.Convert, @As(%f32.97e) [concrete] +// CHECK:STDOUT: %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.type.6a5: type = fn_type @Core.FloatLiteral.as.As.impl.Convert, @Core.FloatLiteral.as.As.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.6af: %Core.FloatLiteral.as.As.impl.Convert.type.6a5 = struct_value () [symbolic] +// CHECK:STDOUT: %As.impl_witness.1e4: = impl_witness imports.%As.impl_witness_table, @Core.FloatLiteral.as.As.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.type.73e: type = fn_type @Core.FloatLiteral.as.As.impl.Convert, @Core.FloatLiteral.as.As.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.7b2: %Core.FloatLiteral.as.As.impl.Convert.type.73e = struct_value () [concrete] +// CHECK:STDOUT: %As.facet: %As.type.114 = facet_value Core.FloatLiteral, (%As.impl_witness.1e4) [concrete] +// CHECK:STDOUT: %.b33: type = fn_type_with_self_type %As.Convert.type.f5e, %As.facet [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.bound: = bound_method %float.c64, %Core.FloatLiteral.as.As.impl.Convert.7b2 [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.specific_fn: = specific_function %Core.FloatLiteral.as.As.impl.Convert.7b2, @Core.FloatLiteral.as.As.impl.Convert(%int_32) [concrete] +// CHECK:STDOUT: %bound_method: = bound_method %float.c64, %Core.FloatLiteral.as.As.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %float.4cb: %f32.97e = float_value 0.800000011 [concrete] +// CHECK:STDOUT: %Float.as.Destroy.impl.Op.type.1b1: type = fn_type @Float.as.Destroy.impl.Op, @Float.as.Destroy.impl(%int_32) [concrete] +// CHECK:STDOUT: %Float.as.Destroy.impl.Op.199: %Float.as.Destroy.impl.Op.type.1b1 = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .foo = %foo.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import_ref.2c9: @Core.FloatLiteral.as.As.impl.%Core.FloatLiteral.as.As.impl.Convert.type (%Core.FloatLiteral.as.As.impl.Convert.type.6a5) = import_ref Core//prelude/parts/float, loc20_41, loaded [symbolic = @Core.FloatLiteral.as.As.impl.%Core.FloatLiteral.as.As.impl.Convert (constants.%Core.FloatLiteral.as.As.impl.Convert.6af)] +// CHECK:STDOUT: %As.impl_witness_table = impl_witness_table (%Core.import_ref.2c9), @Core.FloatLiteral.as.As.impl [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %float: Core.FloatLiteral = float_literal_value 8e-1 [concrete = constants.%float.c64] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %f32: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32.97e] +// CHECK:STDOUT: %impl.elem0: %.b33 = impl_witness_access constants.%As.impl_witness.1e4, element0 [concrete = constants.%Core.FloatLiteral.as.As.impl.Convert.7b2] +// CHECK:STDOUT: %bound_method.loc8_15.1: = bound_method %float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.As.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @Core.FloatLiteral.as.As.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.As.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc8_15.2: = bound_method %float, %specific_fn [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.call: init %f32.97e = call %bound_method.loc8_15.2(%float) [concrete = constants.%float.4cb] +// CHECK:STDOUT: %.loc8_15.1: %f32.97e = value_of_initializer %Core.FloatLiteral.as.As.impl.Convert.call [concrete = constants.%float.4cb] +// CHECK:STDOUT: %.loc8_15.2: %f32.97e = converted %float, %.loc8_15.1 [concrete = constants.%float.4cb] +// CHECK:STDOUT: %.loc8_15.3: ref %f32.97e = temporary_storage +// CHECK:STDOUT: %.loc8_15.4: ref %f32.97e = temporary %.loc8_15.3, %.loc8_15.2 +// CHECK:STDOUT: %addr.loc8_21: %ptr.0bc = addr_of %.loc8_15.4 +// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_21) +// CHECK:STDOUT: %Float.as.Destroy.impl.Op.bound: = bound_method %.loc8_15.3, constants.%Float.as.Destroy.impl.Op.199 +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method.loc8_15.3: = bound_method %.loc8_15.3, %Float.as.Destroy.impl.Op.specific_fn +// CHECK:STDOUT: %addr.loc8_15: %ptr.0bc = addr_of %.loc8_15.3 +// CHECK:STDOUT: %Float.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method.loc8_15.3(%addr.loc8_15) +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- import_double_param.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -1406,6 +1617,81 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- import_float128_param.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %int_128: Core.IntLiteral = int_value 128 [concrete] +// CHECK:STDOUT: %f128.b8c: type = class_type @Float, @Float(%int_128) [concrete] +// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] +// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] +// CHECK:STDOUT: %ptr.402: type = ptr_type %f128.b8c [concrete] +// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] +// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: %float.c64: Core.FloatLiteral = float_literal_value 8e-1 [concrete] +// CHECK:STDOUT: %As.type.d2d: type = facet_type <@As, @As(%f128.b8c)> [concrete] +// CHECK:STDOUT: %As.Convert.type.3bf: type = fn_type @As.Convert, @As(%f128.b8c) [concrete] +// CHECK:STDOUT: %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.type.6a5: type = fn_type @Core.FloatLiteral.as.As.impl.Convert, @Core.FloatLiteral.as.As.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.6af: %Core.FloatLiteral.as.As.impl.Convert.type.6a5 = struct_value () [symbolic] +// CHECK:STDOUT: %As.impl_witness.8a8: = impl_witness imports.%As.impl_witness_table, @Core.FloatLiteral.as.As.impl(%int_128) [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.type.22a: type = fn_type @Core.FloatLiteral.as.As.impl.Convert, @Core.FloatLiteral.as.As.impl(%int_128) [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.e57: %Core.FloatLiteral.as.As.impl.Convert.type.22a = struct_value () [concrete] +// CHECK:STDOUT: %As.facet: %As.type.d2d = facet_value Core.FloatLiteral, (%As.impl_witness.8a8) [concrete] +// CHECK:STDOUT: %.df5: type = fn_type_with_self_type %As.Convert.type.3bf, %As.facet [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.bound: = bound_method %float.c64, %Core.FloatLiteral.as.As.impl.Convert.e57 [concrete] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.specific_fn: = specific_function %Core.FloatLiteral.as.As.impl.Convert.e57, @Core.FloatLiteral.as.As.impl.Convert(%int_128) [concrete] +// CHECK:STDOUT: %bound_method: = bound_method %float.c64, %Core.FloatLiteral.as.As.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %float.709: %f128.b8c = float_value 0.800000000000000000000000000000000039 [concrete] +// CHECK:STDOUT: %Float.as.Destroy.impl.Op.type.0e0: type = fn_type @Float.as.Destroy.impl.Op, @Float.as.Destroy.impl(%int_128) [concrete] +// CHECK:STDOUT: %Float.as.Destroy.impl.Op.052: %Float.as.Destroy.impl.Op.type.0e0 = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .foo = %foo.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import_ref.2c9: @Core.FloatLiteral.as.As.impl.%Core.FloatLiteral.as.As.impl.Convert.type (%Core.FloatLiteral.as.As.impl.Convert.type.6a5) = import_ref Core//prelude/parts/float, loc20_41, loaded [symbolic = @Core.FloatLiteral.as.As.impl.%Core.FloatLiteral.as.As.impl.Convert (constants.%Core.FloatLiteral.as.As.impl.Convert.6af)] +// CHECK:STDOUT: %As.impl_witness_table = impl_witness_table (%Core.import_ref.2c9), @Core.FloatLiteral.as.As.impl [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %float: Core.FloatLiteral = float_literal_value 8e-1 [concrete = constants.%float.c64] +// CHECK:STDOUT: %int_128: Core.IntLiteral = int_value 128 [concrete = constants.%int_128] +// CHECK:STDOUT: %f128: type = class_type @Float, @Float(constants.%int_128) [concrete = constants.%f128.b8c] +// CHECK:STDOUT: %impl.elem0: %.df5 = impl_witness_access constants.%As.impl_witness.8a8, element0 [concrete = constants.%Core.FloatLiteral.as.As.impl.Convert.e57] +// CHECK:STDOUT: %bound_method.loc8_15.1: = bound_method %float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.As.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @Core.FloatLiteral.as.As.impl.Convert(constants.%int_128) [concrete = constants.%Core.FloatLiteral.as.As.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc8_15.2: = bound_method %float, %specific_fn [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.FloatLiteral.as.As.impl.Convert.call: init %f128.b8c = call %bound_method.loc8_15.2(%float) [concrete = constants.%float.709] +// CHECK:STDOUT: %.loc8_15.1: %f128.b8c = value_of_initializer %Core.FloatLiteral.as.As.impl.Convert.call [concrete = constants.%float.709] +// CHECK:STDOUT: %.loc8_15.2: %f128.b8c = converted %float, %.loc8_15.1 [concrete = constants.%float.709] +// CHECK:STDOUT: %.loc8_15.3: ref %f128.b8c = temporary_storage +// CHECK:STDOUT: %.loc8_15.4: ref %f128.b8c = temporary %.loc8_15.3, %.loc8_15.2 +// CHECK:STDOUT: %addr.loc8_22: %ptr.402 = addr_of %.loc8_15.4 +// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_22) +// CHECK:STDOUT: %Float.as.Destroy.impl.Op.bound: = bound_method %.loc8_15.3, constants.%Float.as.Destroy.impl.Op.052 +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method.loc8_15.3: = bound_method %.loc8_15.3, %Float.as.Destroy.impl.Op.specific_fn +// CHECK:STDOUT: %addr.loc8_15: %ptr.402 = addr_of %.loc8_15.3 +// CHECK:STDOUT: %Float.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method.loc8_15.3(%addr.loc8_15) +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- import_bool_return.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/interop/cpp/function/param_unsupported.carbon b/toolchain/check/testdata/interop/cpp/function/param_unsupported.carbon index 347c666b5d20..e056853cea22 100644 --- a/toolchain/check/testdata/interop/cpp/function/param_unsupported.carbon +++ b/toolchain/check/testdata/interop/cpp/function/param_unsupported.carbon @@ -16,7 +16,7 @@ // --- unsupported_primitive_type.h -auto foo(float a) -> void; +auto foo(_BitInt(23) a) -> void; // --- fail_todo_import_unsupported_primitive_type.carbon @@ -26,14 +26,14 @@ import Cpp library "unsupported_primitive_type.h"; fn F() { //@dump-sem-ir-begin - // CHECK:STDERR: fail_todo_import_unsupported_primitive_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: float` [SemanticsTodo] - // CHECK:STDERR: Cpp.foo(1.1); + // CHECK:STDERR: fail_todo_import_unsupported_primitive_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: _BitInt(23)` [SemanticsTodo] + // CHECK:STDERR: Cpp.foo(11); // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: fail_todo_import_unsupported_primitive_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup] - // CHECK:STDERR: Cpp.foo(1.1); + // CHECK:STDERR: Cpp.foo(11); // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: - Cpp.foo(1.1); + Cpp.foo(11); //@dump-sem-ir-end } @@ -43,7 +43,7 @@ fn F() { // --- unsupported_primitive_type_among_params.h -auto foo(int a, float b) -> void; +auto foo(int a, _BitInt(23) b) -> void; // --- fail_todo_import_unsupported_primitive_type_among_params.carbon @@ -53,21 +53,21 @@ import Cpp library "unsupported_primitive_type_among_params.h"; fn F() { //@dump-sem-ir-begin - // CHECK:STDERR: fail_todo_import_unsupported_primitive_type_among_params.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: float` [SemanticsTodo] - // CHECK:STDERR: Cpp.foo(1, 2.0); + // CHECK:STDERR: fail_todo_import_unsupported_primitive_type_among_params.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: _BitInt(23)` [SemanticsTodo] + // CHECK:STDERR: Cpp.foo(1, 20); // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: fail_todo_import_unsupported_primitive_type_among_params.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup] - // CHECK:STDERR: Cpp.foo(1, 2.0); + // CHECK:STDERR: Cpp.foo(1, 20); // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: - Cpp.foo(1, 2.0); + Cpp.foo(1, 20); //@dump-sem-ir-end } // CHECK:STDOUT: --- fail_todo_import_unsupported_primitive_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %float: Core.FloatLiteral = float_literal_value 11e-1 [concrete] +// CHECK:STDOUT: %int_11: Core.IntLiteral = int_value 11 [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -81,7 +81,7 @@ fn F() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %foo.ref: = name_ref foo, [concrete = ] -// CHECK:STDOUT: %float: Core.FloatLiteral = float_literal_value 11e-1 [concrete = constants.%float] +// CHECK:STDOUT: %int_11: Core.IntLiteral = int_value 11 [concrete = constants.%int_11] // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: @@ -89,7 +89,7 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete] -// CHECK:STDOUT: %float: Core.FloatLiteral = float_literal_value 20e-1 [concrete] +// CHECK:STDOUT: %int_20: Core.IntLiteral = int_value 20 [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -104,7 +104,7 @@ fn F() { // CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %foo.ref: = name_ref foo, [concrete = ] // CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1] -// CHECK:STDOUT: %float: Core.FloatLiteral = float_literal_value 20e-1 [concrete = constants.%float] +// CHECK:STDOUT: %int_20: Core.IntLiteral = int_value 20 [concrete = constants.%int_20] // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/primitives/numeric_literals.carbon b/toolchain/check/testdata/primitives/numeric_literals.carbon index 320cff6a6aa7..5e6e56f608eb 100644 --- a/toolchain/check/testdata/primitives/numeric_literals.carbon +++ b/toolchain/check/testdata/primitives/numeric_literals.carbon @@ -92,7 +92,7 @@ let max_rounds_down_hex: f64 = 0x1.FFFFFFFFFFFFF7FFFFFFFFFFp+1023; library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_overflow_very_large_mantissa.carbon:[[@LINE+4]]:22: error: value 399999999999999999999999999999999999999999999999999999999999999999999990*10^237 too large for floating-point type `f64` [FloatTooLargeForType] +// CHECK:STDERR: fail_overflow_very_large_mantissa.carbon:[[@LINE+4]]:22: error: value 399999999999999999999999999999999999999999999999999999999999999999999990*10^237 too large for floating-point type `f64` [FloatLiteralTooLargeForType] // CHECK:STDERR: let too_large: f64 = 39999999999999999999999999999999999999999999999999999999999999999999999.0e238; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -105,19 +105,19 @@ let max_plus_one: f64 = 17976931348623157081452742373170435679807056752584499659 let max_plus_a_bit_hex: f64 = 0x1.FFFFFFFFFFFFF00000000000000000000001p+1023; // The smallest number that would round to having an over-large exponent. -// CHECK:STDERR: fail_overflow_very_large_mantissa.carbon:[[@LINE+4]]:30: error: value 1797693134862315807937289714053034150799341327100378269361737789804449682927647509466490179775872070963302864166928879109465555478519404026306574886715058206819089020007083836762738548458177115317644757302700698555713669596228429148198608349364752927190741684443655107043427115596995080930428801779041744977920*10^-1 too large for floating-point type `f64` [FloatTooLargeForType] +// CHECK:STDERR: fail_overflow_very_large_mantissa.carbon:[[@LINE+4]]:30: error: value 1797693134862315807937289714053034150799341327100378269361737789804449682927647509466490179775872070963302864166928879109465555478519404026306574886715058206819089020007083836762738548458177115317644757302700698555713669596228429148198608349364752927190741684443655107043427115596995080930428801779041744977920*10^-1 too large for floating-point type `f64` [FloatLiteralTooLargeForType] // CHECK:STDERR: let min_rounds_to_inf: f64 = 179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792.0; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: let min_rounds_to_inf: f64 = 179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792.0; -// CHECK:STDERR: fail_overflow_very_large_mantissa.carbon:[[@LINE+4]]:41: error: value 179769313486231580793728971405303415079934132710037826936173778980444969*10^237 too large for floating-point type `f64` [FloatTooLargeForType] +// CHECK:STDERR: fail_overflow_very_large_mantissa.carbon:[[@LINE+4]]:41: error: value 179769313486231580793728971405303415079934132710037826936173778980444969*10^237 too large for floating-point type `f64` [FloatLiteralTooLargeForType] // CHECK:STDERR: let min_rounds_to_inf_rounded_up: f64 = 17976931348623158079372897140530341507993413271003782693617377898044496.9e238; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: let min_rounds_to_inf_rounded_up: f64 = 17976931348623158079372897140530341507993413271003782693617377898044496.9e238; -// CHECK:STDERR: fail_overflow_very_large_mantissa.carbon:[[@LINE+4]]:34: error: value 144115188075855864*2^967 too large for floating-point type `f64` [FloatTooLargeForType] +// CHECK:STDERR: fail_overflow_very_large_mantissa.carbon:[[@LINE+4]]:34: error: value 144115188075855864*2^967 too large for floating-point type `f64` [FloatLiteralTooLargeForType] // CHECK:STDERR: let min_rounds_to_inf_hex: f64 = 0x1.FFFFFFFFFFFFF8p+1023; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -127,7 +127,7 @@ let min_rounds_to_inf_hex: f64 = 0x1.FFFFFFFFFFFFF8p+1023; library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_overflow_very_large_exponent.carbon:[[@LINE+4]]:14: error: value 50*10^39999999999999999992 too large for floating-point type `f64` [FloatTooLargeForType] +// CHECK:STDERR: fail_overflow_very_large_exponent.carbon:[[@LINE+4]]:14: error: value 50*10^39999999999999999992 too large for floating-point type `f64` [FloatLiteralTooLargeForType] // CHECK:STDERR: let e: f64 = 5.0e39999999999999999993; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/primitives/type_literals.carbon b/toolchain/check/testdata/primitives/type_literals.carbon index 433058488740..3bb9f2549879 100644 --- a/toolchain/check/testdata/primitives/type_literals.carbon +++ b/toolchain/check/testdata/primitives/type_literals.carbon @@ -34,37 +34,11 @@ var test_u64: u64; library "[[@TEST_NAME]]"; //@dump-sem-ir-begin -var test_f64: f64; -//@dump-sem-ir-end - -// --- fail_todo_fN_unsupported.carbon -library "[[@TEST_NAME]]"; - -// TODO: Some or all of these should eventually work. -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] -// CHECK:STDERR: adapt MakeFloat(N); -// CHECK:STDERR: ^~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_fN_unsupported.carbon:[[@LINE+4]]:15: note: in `f16` used here [ResolvingSpecificHere] -// CHECK:STDERR: var test_f16: f16; -// CHECK:STDERR: ^~~ -// CHECK:STDERR: var test_f16: f16; -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] -// CHECK:STDERR: adapt MakeFloat(N); -// CHECK:STDERR: ^~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_fN_unsupported.carbon:[[@LINE+4]]:15: note: in `f32` used here [ResolvingSpecificHere] -// CHECK:STDERR: var test_f32: f32; -// CHECK:STDERR: ^~~ -// CHECK:STDERR: var test_f32: f32; -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] -// CHECK:STDERR: adapt MakeFloat(N); -// CHECK:STDERR: ^~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_fN_unsupported.carbon:[[@LINE+4]]:16: note: in `f128` used here [ResolvingSpecificHere] -// CHECK:STDERR: var test_f128: f128; -// CHECK:STDERR: ^~~~ -// CHECK:STDERR: +var test_f64: f64; var test_f128: f128; +//@dump-sem-ir-end // --- string.carbon @@ -164,7 +138,7 @@ library "[[@TEST_NAME]]"; // CHECK:STDERR: ^~ // CHECK:STDERR: var test_f0: f0; -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] +// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: unsupported floating-point bit width 1 [CompileTimeFloatBitWidth] // CHECK:STDERR: adapt MakeFloat(N); // CHECK:STDERR: ^~~~~~~~~~~~ // CHECK:STDERR: fail_fN_bad_width.carbon:[[@LINE+4]]:14: note: in `f1` used here [ResolvingSpecificHere] @@ -172,7 +146,7 @@ var test_f0: f0; // CHECK:STDERR: ^~ // CHECK:STDERR: var test_f1: f1; -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] +// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: unsupported floating-point bit width 15 [CompileTimeFloatBitWidth] // CHECK:STDERR: adapt MakeFloat(N); // CHECK:STDERR: ^~~~~~~~~~~~ // CHECK:STDERR: fail_fN_bad_width.carbon:[[@LINE+4]]:15: note: in `f15` used here [ResolvingSpecificHere] @@ -180,7 +154,16 @@ var test_f1: f1; // CHECK:STDERR: ^~~ // CHECK:STDERR: var test_f15: f15; -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] +// TODO: Decide if we want to expose the x87 80-bit floating point type this way. +// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: unsupported floating-point bit width 80 [CompileTimeFloatBitWidth] +// CHECK:STDERR: adapt MakeFloat(N); +// CHECK:STDERR: ^~~~~~~~~~~~ +// CHECK:STDERR: fail_fN_bad_width.carbon:[[@LINE+4]]:15: note: in `f80` used here [ResolvingSpecificHere] +// CHECK:STDERR: var test_f80: f80; +// CHECK:STDERR: ^~~ +// CHECK:STDERR: +var test_f80: f80; +// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: unsupported floating-point bit width 100 [CompileTimeFloatBitWidth] // CHECK:STDERR: adapt MakeFloat(N); // CHECK:STDERR: ^~~~~~~~~~~~ // CHECK:STDERR: fail_fN_bad_width.carbon:[[@LINE+4]]:16: note: in `f100` used here [ResolvingSpecificHere] @@ -188,7 +171,7 @@ var test_f15: f15; // CHECK:STDERR: ^~~~ // CHECK:STDERR: var test_f100: f100; -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] +// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: unsupported floating-point bit width 1000000000 [CompileTimeFloatBitWidth] // CHECK:STDERR: adapt MakeFloat(N); // CHECK:STDERR: ^~~~~~~~~~~~ // CHECK:STDERR: fail_fN_bad_width.carbon:[[@LINE+4]]:23: note: in `f1000000000` used here [ResolvingSpecificHere] @@ -196,7 +179,7 @@ var test_f100: f100; // CHECK:STDERR: ^~~~~~~~~~~ // CHECK:STDERR: var test_f1000000000: f1000000000; -// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: bit width must be 64 [CompileTimeFloatBitWidth] +// CHECK:STDERR: min_prelude/parts/float.carbon:11:9: error: unsupported floating-point bit width 1000000000000 [CompileTimeFloatBitWidth] // CHECK:STDERR: adapt MakeFloat(N); // CHECK:STDERR: ^~~~~~~~~~~~ // CHECK:STDERR: fail_fN_bad_width.carbon:[[@LINE+4]]:26: note: in `f1000000000000` used here [ResolvingSpecificHere] @@ -347,9 +330,18 @@ var x: type = 42; // CHECK:STDOUT: --- fN.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { +// CHECK:STDOUT: %int_16: Core.IntLiteral = int_value 16 [concrete] +// CHECK:STDOUT: %f16.a6a: type = class_type @Float, @Float(%int_16) [concrete] +// CHECK:STDOUT: %pattern_type.cd1: type = pattern_type %f16.a6a [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %f32.97e: type = class_type @Float, @Float(%int_32) [concrete] +// CHECK:STDOUT: %pattern_type.201: type = pattern_type %f32.97e [concrete] // CHECK:STDOUT: %int_64: Core.IntLiteral = int_value 64 [concrete] // CHECK:STDOUT: %f64.d77: type = class_type @Float, @Float(%int_64) [concrete] // CHECK:STDOUT: %pattern_type.0ae: type = pattern_type %f64.d77 [concrete] +// CHECK:STDOUT: %int_128: Core.IntLiteral = int_value 128 [concrete] +// CHECK:STDOUT: %f128.b8c: type = class_type @Float, @Float(%int_128) [concrete] +// CHECK:STDOUT: %pattern_type.22c: type = pattern_type %f128.b8c [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -357,15 +349,45 @@ var x: type = 42; // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %test_f16.patt: %pattern_type.cd1 = binding_pattern test_f16 [concrete] +// CHECK:STDOUT: %test_f16.var_patt: %pattern_type.cd1 = var_pattern %test_f16.patt [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: %test_f16.var: ref %f16.a6a = var %test_f16.var_patt [concrete] +// CHECK:STDOUT: %.loc4: type = splice_block %f16 [concrete = constants.%f16.a6a] { +// CHECK:STDOUT: %int_16: Core.IntLiteral = int_value 16 [concrete = constants.%int_16] +// CHECK:STDOUT: %f16: type = class_type @Float, @Float(constants.%int_16) [concrete = constants.%f16.a6a] +// CHECK:STDOUT: } +// CHECK:STDOUT: %test_f16: ref %f16.a6a = bind_name test_f16, %test_f16.var [concrete = %test_f16.var] +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %test_f32.patt: %pattern_type.201 = binding_pattern test_f32 [concrete] +// CHECK:STDOUT: %test_f32.var_patt: %pattern_type.201 = var_pattern %test_f32.patt [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: %test_f32.var: ref %f32.97e = var %test_f32.var_patt [concrete] +// CHECK:STDOUT: %.loc5: type = splice_block %f32 [concrete = constants.%f32.97e] { +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %f32: type = class_type @Float, @Float(constants.%int_32) [concrete = constants.%f32.97e] +// CHECK:STDOUT: } +// CHECK:STDOUT: %test_f32: ref %f32.97e = bind_name test_f32, %test_f32.var [concrete = %test_f32.var] +// CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %test_f64.patt: %pattern_type.0ae = binding_pattern test_f64 [concrete] // CHECK:STDOUT: %test_f64.var_patt: %pattern_type.0ae = var_pattern %test_f64.patt [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: %test_f64.var: ref %f64.d77 = var %test_f64.var_patt [concrete] -// CHECK:STDOUT: %.loc4: type = splice_block %f64 [concrete = constants.%f64.d77] { +// CHECK:STDOUT: %.loc6: type = splice_block %f64 [concrete = constants.%f64.d77] { // CHECK:STDOUT: %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64] // CHECK:STDOUT: %f64: type = class_type @Float, @Float(constants.%int_64) [concrete = constants.%f64.d77] // CHECK:STDOUT: } // CHECK:STDOUT: %test_f64: ref %f64.d77 = bind_name test_f64, %test_f64.var [concrete = %test_f64.var] +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %test_f128.patt: %pattern_type.22c = binding_pattern test_f128 [concrete] +// CHECK:STDOUT: %test_f128.var_patt: %pattern_type.22c = var_pattern %test_f128.patt [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: %test_f128.var: ref %f128.b8c = var %test_f128.var_patt [concrete] +// CHECK:STDOUT: %.loc7: type = splice_block %f128 [concrete = constants.%f128.b8c] { +// CHECK:STDOUT: %int_128: Core.IntLiteral = int_value 128 [concrete = constants.%int_128] +// CHECK:STDOUT: %f128: type = class_type @Float, @Float(constants.%int_128) [concrete = constants.%f128.b8c] +// CHECK:STDOUT: } +// CHECK:STDOUT: %test_f128: ref %f128.b8c = bind_name test_f128, %test_f128.var [concrete = %test_f128.var] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- string.carbon diff --git a/toolchain/check/type.cpp b/toolchain/check/type.cpp index 26f64164546a..1e29844080d6 100644 --- a/toolchain/check/type.cpp +++ b/toolchain/check/type.cpp @@ -8,10 +8,10 @@ #include "toolchain/check/facet_type.h" #include "toolchain/check/type_completion.h" #include "toolchain/sem_ir/facet_type_info.h" +#include "toolchain/sem_ir/ids.h" namespace Carbon::Check { -// Enforces that an integer type has a valid bit width. auto ValidateIntType(Context& context, SemIR::LocId loc_id, SemIR::IntType result) -> bool { auto bit_width = @@ -44,29 +44,54 @@ auto ValidateIntType(Context& context, SemIR::LocId loc_id, return true; } -// Enforces that the bit width is 64 for a float. -auto ValidateFloatBitWidth(Context& context, SemIR::LocId loc_id, - SemIR::InstId inst_id) -> bool { - auto inst = context.insts().GetAs(inst_id); - if (context.ints().Get(inst.int_id) == 64) { - return true; - } - - CARBON_DIAGNOSTIC(CompileTimeFloatBitWidth, Error, "bit width must be 64"); - context.emitter().Emit(loc_id, CompileTimeFloatBitWidth); - return false; -} - -// Enforces that a float type has a valid bit width. -auto ValidateFloatType(Context& context, SemIR::LocId loc_id, - SemIR::FloatType result) -> bool { - auto bit_width = +auto ValidateFloatTypeAndSetKind(Context& context, SemIR::LocId loc_id, + SemIR::FloatType& result) -> bool { + // Get the bit width value. + auto bit_width_inst = context.insts().TryGetAs(result.bit_width_id); - if (!bit_width) { - // Symbolic bit width. + if (!bit_width_inst) { + // Symbolic bit width. Defer checking until we have a concrete value. return true; } - return ValidateFloatBitWidth(context, loc_id, result.bit_width_id); + auto bit_width = context.ints().Get(bit_width_inst->int_id); + + // If no kind is specified, infer kind from width. + if (!result.float_kind.has_value()) { + switch (bit_width.getLimitedValue()) { + case 16: + result.float_kind = SemIR::FloatKind::Binary16; + break; + case 32: + result.float_kind = SemIR::FloatKind::Binary32; + break; + case 64: + result.float_kind = SemIR::FloatKind::Binary64; + break; + case 128: + result.float_kind = SemIR::FloatKind::Binary128; + break; + default: + CARBON_DIAGNOSTIC(CompileTimeFloatBitWidth, Error, + "unsupported floating-point bit width {0}", TypedInt); + context.emitter().Emit(loc_id, CompileTimeFloatBitWidth, + TypedInt(bit_width_inst->type_id, bit_width)); + return false; + } + } + + if (llvm::APFloat::semanticsSizeInBits(result.float_kind.Semantics()) != + bit_width) { + // This can't currently happen because we don't provide any way to set the + // float kind other than through the bit width. + // TODO: Add a float_type.make builtin that takes a float kind, and add a + // diagnostic here if the size is wrong. + context.TODO(loc_id, "wrong size for float type"); + return false; + } + + // TODO: Diagnose if the floating-point type is not supported on this target? + + return true; } // Gets or forms a type_id for a type, given the instruction kind and arguments. diff --git a/toolchain/check/type.h b/toolchain/check/type.h index f9a706879683..496cb2d07065 100644 --- a/toolchain/check/type.h +++ b/toolchain/check/type.h @@ -15,13 +15,10 @@ namespace Carbon::Check { auto ValidateIntType(Context& context, SemIR::LocId loc_id, SemIR::IntType result) -> bool; -// Enforces that the bit width is 64 for a float. -auto ValidateFloatBitWidth(Context& context, SemIR::LocId loc_id, - SemIR::InstId inst_id) -> bool; - -// Enforces that a float type has a valid bit width. -auto ValidateFloatType(Context& context, SemIR::LocId loc_id, - SemIR::FloatType result) -> bool; +// Enforces that a float type has a valid bit width. If the `float_kind` field +// is `None`, sets it to a suitable kind for the bit width. +auto ValidateFloatTypeAndSetKind(Context& context, SemIR::LocId loc_id, + SemIR::FloatType& result) -> bool; // Gets the type to use for an unbound associated entity declared in this // interface. For example, this is the type of `I.T` after diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index 22ae3e4784f3..59cad23b0709 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -423,6 +423,7 @@ CARBON_DIAGNOSTIC_KIND(IncompleteTypeInValueConversion) CARBON_DIAGNOSTIC_KIND(InCopy) CARBON_DIAGNOSTIC_KIND(CharTooLargeForType) CARBON_DIAGNOSTIC_KIND(IntTooLargeForType) +CARBON_DIAGNOSTIC_KIND(FloatLiteralTooLargeForType) CARBON_DIAGNOSTIC_KIND(FloatTooLargeForType) CARBON_DIAGNOSTIC_KIND(IntWidthNotMultipleOf8) CARBON_DIAGNOSTIC_KIND(IntWidthNotPositive) diff --git a/toolchain/lower/file_context.cpp b/toolchain/lower/file_context.cpp index c266b1ab92d8..1f959c94dbe2 100644 --- a/toolchain/lower/file_context.cpp +++ b/toolchain/lower/file_context.cpp @@ -794,10 +794,10 @@ static auto BuildTypeForInst(FileContext& /*context*/, return nullptr; } -static auto BuildTypeForInst(FileContext& context, SemIR::FloatType /*inst*/) +static auto BuildTypeForInst(FileContext& context, SemIR::FloatType inst) -> llvm::Type* { - // TODO: Handle different sizes. - return llvm::Type::getDoubleTy(context.llvm_context()); + return llvm::Type::getFloatingPointTy(context.llvm_context(), + inst.float_kind.Semantics()); } static auto BuildTypeForInst(FileContext& context, SemIR::IntType inst) diff --git a/toolchain/lower/testdata/builtins/float.carbon b/toolchain/lower/testdata/builtins/float.carbon index 220b36deccb5..c410658828d1 100644 --- a/toolchain/lower/testdata/builtins/float.carbon +++ b/toolchain/lower/testdata/builtins/float.carbon @@ -63,6 +63,22 @@ fn TestMul(a: f64*, b: f64) { Mul(a, b); } fn Div(a: f64*, b: f64) = "float.div_assign"; fn TestDiv(a: f64*, b: f64) { Div(a, b); } +// --- types.carbon + +library "[[@TEST_NAME]]"; + +fn F16(a: f16, b: f16) -> f16 = "float.add"; +fn TestF16(a: f16, b: f16) -> f16 { return F16(a, b); } + +fn F32(a: f32, b: f32) -> f32 = "float.add"; +fn TestF32(a: f32, b: f32) -> f32 { return F32(a, b); } + +fn F64(a: f64, b: f64) -> f64 = "float.add"; +fn TestF64(a: f64, b: f64) -> f64 { return F64(a, b); } + +fn F128(a: f128, b: f128) -> f128 = "float.add"; +fn TestF128(a: f128, b: f128) -> f128 { return F128(a, b); } + // CHECK:STDOUT: ; ModuleID = 'basic.carbon' // CHECK:STDOUT: source_filename = "basic.carbon" // CHECK:STDOUT: @@ -230,3 +246,51 @@ fn TestDiv(a: f64*, b: f64) { Div(a, b); } // CHECK:STDOUT: !15 = distinct !DISubprogram(name: "TestDiv", linkageName: "_CTestDiv.Main", scope: null, file: !3, line: 14, type: !5, spFlags: DISPFlagDefinition, unit: !2) // CHECK:STDOUT: !16 = !DILocation(line: 14, column: 31, scope: !15) // CHECK:STDOUT: !17 = !DILocation(line: 14, column: 1, scope: !15) +// CHECK:STDOUT: ; ModuleID = 'types.carbon' +// CHECK:STDOUT: source_filename = "types.carbon" +// CHECK:STDOUT: +// CHECK:STDOUT: define half @_CTestF16.Main(half %a, half %b) !dbg !4 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %F16.call = fadd half %a, %b, !dbg !7 +// CHECK:STDOUT: ret half %F16.call, !dbg !8 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: define float @_CTestF32.Main(float %a, float %b) !dbg !9 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %F32.call = fadd float %a, %b, !dbg !10 +// CHECK:STDOUT: ret float %F32.call, !dbg !11 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: define double @_CTestF64.Main(double %a, double %b) !dbg !12 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %F64.call = fadd double %a, %b, !dbg !13 +// CHECK:STDOUT: ret double %F64.call, !dbg !14 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: define fp128 @_CTestF128.Main(fp128 %a, fp128 %b) !dbg !15 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %F128.call = fadd fp128 %a, %b, !dbg !16 +// CHECK:STDOUT: ret fp128 %F128.call, !dbg !17 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: !llvm.module.flags = !{!0, !1} +// CHECK:STDOUT: !llvm.dbg.cu = !{!2} +// CHECK:STDOUT: +// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5} +// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3} +// CHECK:STDOUT: !2 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +// CHECK:STDOUT: !3 = !DIFile(filename: "types.carbon", directory: "") +// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "TestF16", linkageName: "_CTestF16.Main", scope: null, file: !3, line: 5, type: !5, spFlags: DISPFlagDefinition, unit: !2) +// CHECK:STDOUT: !5 = !DISubroutineType(types: !6) +// CHECK:STDOUT: !6 = !{} +// CHECK:STDOUT: !7 = !DILocation(line: 5, column: 44, scope: !4) +// CHECK:STDOUT: !8 = !DILocation(line: 5, column: 37, scope: !4) +// CHECK:STDOUT: !9 = distinct !DISubprogram(name: "TestF32", linkageName: "_CTestF32.Main", scope: null, file: !3, line: 8, type: !5, spFlags: DISPFlagDefinition, unit: !2) +// CHECK:STDOUT: !10 = !DILocation(line: 8, column: 44, scope: !9) +// CHECK:STDOUT: !11 = !DILocation(line: 8, column: 37, scope: !9) +// CHECK:STDOUT: !12 = distinct !DISubprogram(name: "TestF64", linkageName: "_CTestF64.Main", scope: null, file: !3, line: 11, type: !5, spFlags: DISPFlagDefinition, unit: !2) +// CHECK:STDOUT: !13 = !DILocation(line: 11, column: 44, scope: !12) +// CHECK:STDOUT: !14 = !DILocation(line: 11, column: 37, scope: !12) +// CHECK:STDOUT: !15 = distinct !DISubprogram(name: "TestF128", linkageName: "_CTestF128.Main", scope: null, file: !3, line: 14, type: !5, spFlags: DISPFlagDefinition, unit: !2) +// CHECK:STDOUT: !16 = !DILocation(line: 14, column: 48, scope: !15) +// CHECK:STDOUT: !17 = !DILocation(line: 14, column: 41, scope: !15) diff --git a/toolchain/lower/testdata/builtins/types.carbon b/toolchain/lower/testdata/builtins/types.carbon index 0734e17f4712..d4f672e9a725 100644 --- a/toolchain/lower/testdata/builtins/types.carbon +++ b/toolchain/lower/testdata/builtins/types.carbon @@ -16,11 +16,17 @@ fn Int(size: IntLiteral()) -> type = "int.make_type_signed"; fn Float(size: IntLiteral()) -> type = "float.make_type"; fn Bool() -> type = "bool.make_type"; fn AsI32(n: IntLiteral()) -> Int(32) = "int.convert_checked"; +fn AsF16(f: FloatLiteral()) -> Float(16) = "float.convert_checked"; +fn AsF32(f: FloatLiteral()) -> Float(32) = "float.convert_checked"; fn AsF64(f: FloatLiteral()) -> Float(64) = "float.convert_checked"; +fn AsF128(f: FloatLiteral()) -> Float(128) = "float.convert_checked"; fn F() { - var i: Int(32) = AsI32(0); - var f: Float(64) = AsF64(0.0); + var i: Int(32) = AsI32(1); + var e: Float(16) = AsF16(1.0); + var f: Float(32) = AsF32(1.0); + var g: Float(64) = AsF64(1.0); + var h: Float(128) = AsF128(1.0); var b: Bool() = false; } @@ -30,22 +36,31 @@ fn F() { // CHECK:STDOUT: define void @_CF.Main() !dbg !4 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %i.var = alloca i32, align 4, !dbg !7 -// CHECK:STDOUT: %f.var = alloca double, align 8, !dbg !8 -// CHECK:STDOUT: %b.var = alloca i1, align 1, !dbg !9 +// CHECK:STDOUT: %e.var = alloca half, align 2, !dbg !8 +// CHECK:STDOUT: %f.var = alloca float, align 4, !dbg !9 +// CHECK:STDOUT: %g.var = alloca double, align 8, !dbg !10 +// CHECK:STDOUT: %h.var = alloca fp128, align 16, !dbg !11 +// CHECK:STDOUT: %b.var = alloca i1, align 1, !dbg !12 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(i64 4, ptr %i.var), !dbg !7 -// CHECK:STDOUT: store i32 0, ptr %i.var, align 4, !dbg !7 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(i64 8, ptr %f.var), !dbg !8 -// CHECK:STDOUT: store double 0.000000e+00, ptr %f.var, align 8, !dbg !8 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(i64 1, ptr %b.var), !dbg !9 -// CHECK:STDOUT: store i1 false, ptr %b.var, align 1, !dbg !9 -// CHECK:STDOUT: ret void, !dbg !10 +// CHECK:STDOUT: store i32 1, ptr %i.var, align 4, !dbg !7 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(i64 2, ptr %e.var), !dbg !8 +// CHECK:STDOUT: store half 0xH3C00, ptr %e.var, align 2, !dbg !8 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(i64 4, ptr %f.var), !dbg !9 +// CHECK:STDOUT: store float 1.000000e+00, ptr %f.var, align 4, !dbg !9 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(i64 8, ptr %g.var), !dbg !10 +// CHECK:STDOUT: store double 1.000000e+00, ptr %g.var, align 8, !dbg !10 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(i64 16, ptr %h.var), !dbg !11 +// CHECK:STDOUT: store fp128 0xL00000000000000003FFF000000000000, ptr %h.var, align 16, !dbg !11 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(i64 1, ptr %b.var), !dbg !12 +// CHECK:STDOUT: store i1 false, ptr %b.var, align 1, !dbg !12 +// CHECK:STDOUT: ret void, !dbg !13 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) // CHECK:STDOUT: declare void @llvm.lifetime.start.p0(i64 immarg, ptr captures(none)) #0 // CHECK:STDOUT: // CHECK:STDOUT: ; uselistorder directives -// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 2, 1, 0 } +// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 5, 4, 3, 2, 1, 0 } // CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } // CHECK:STDOUT: @@ -56,10 +71,13 @@ fn F() { // CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3} // CHECK:STDOUT: !2 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) // CHECK:STDOUT: !3 = !DIFile(filename: "types.carbon", directory: "") -// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main", scope: null, file: !3, line: 21, type: !5, spFlags: DISPFlagDefinition, unit: !2) +// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main", scope: null, file: !3, line: 24, type: !5, spFlags: DISPFlagDefinition, unit: !2) // CHECK:STDOUT: !5 = !DISubroutineType(types: !6) // CHECK:STDOUT: !6 = !{} -// CHECK:STDOUT: !7 = !DILocation(line: 22, column: 3, scope: !4) -// CHECK:STDOUT: !8 = !DILocation(line: 23, column: 3, scope: !4) -// CHECK:STDOUT: !9 = !DILocation(line: 24, column: 3, scope: !4) -// CHECK:STDOUT: !10 = !DILocation(line: 21, column: 1, scope: !4) +// CHECK:STDOUT: !7 = !DILocation(line: 25, column: 3, scope: !4) +// CHECK:STDOUT: !8 = !DILocation(line: 26, column: 3, scope: !4) +// CHECK:STDOUT: !9 = !DILocation(line: 27, column: 3, scope: !4) +// CHECK:STDOUT: !10 = !DILocation(line: 28, column: 3, scope: !4) +// CHECK:STDOUT: !11 = !DILocation(line: 29, column: 3, scope: !4) +// CHECK:STDOUT: !12 = !DILocation(line: 30, column: 3, scope: !4) +// CHECK:STDOUT: !13 = !DILocation(line: 24, column: 1, scope: !4) diff --git a/toolchain/sem_ir/ids.cpp b/toolchain/sem_ir/ids.cpp index bd3269743ead..eae947275083 100644 --- a/toolchain/sem_ir/ids.cpp +++ b/toolchain/sem_ir/ids.cpp @@ -78,6 +78,54 @@ auto IntKind::Print(llvm::raw_ostream& out) const -> void { } } +static auto FloatKindToStringLiteral(FloatKind kind) -> llvm::StringLiteral { + switch (kind.index) { + case FloatKind::None.index: + return ""; + case FloatKind::Binary16.index: + return "f16"; + case FloatKind::Binary32.index: + return "f32"; + case FloatKind::Binary64.index: + return "f64"; + case FloatKind::Binary128.index: + return "f128"; + case FloatKind::BFloat16.index: + return "f16_brain"; + case FloatKind::X87Float80.index: + return "f80_x87"; + case FloatKind::PPCFloat128.index: + return "f128_ppc"; + default: + return ""; + } +} + +auto FloatKind::Print(llvm::raw_ostream& out) const -> void { + out << FloatKindToStringLiteral(*this); +} + +auto FloatKind::Semantics() const -> const llvm::fltSemantics& { + switch (this->index) { + case Binary16.index: + return llvm::APFloat::IEEEhalf(); + case Binary32.index: + return llvm::APFloat::IEEEsingle(); + case Binary64.index: + return llvm::APFloat::IEEEdouble(); + case Binary128.index: + return llvm::APFloat::IEEEquad(); + case BFloat16.index: + return llvm::APFloat::BFloat(); + case X87Float80.index: + return llvm::APFloat::x87DoubleExtended(); + case PPCFloat128.index: + return llvm::APFloat::PPCDoubleDouble(); + default: + CARBON_FATAL("Unexpected float kind {0}", *this); + } +} + // Double-check the special value mapping and constexpr evaluation. static_assert(NameId::SpecialNameId::Vptr == *NameId::Vptr.AsSpecialNameId()); diff --git a/toolchain/sem_ir/ids.h b/toolchain/sem_ir/ids.h index 389c3601de78..a0388b344a81 100644 --- a/toolchain/sem_ir/ids.h +++ b/toolchain/sem_ir/ids.h @@ -9,6 +9,7 @@ #include "common/check.h" #include "common/ostream.h" +#include "llvm/ADT/APFloat.h" #include "toolchain/base/index_base.h" #include "toolchain/base/value_ids.h" #include "toolchain/diagnostics/diagnostic_emitter.h" @@ -503,16 +504,52 @@ struct IntKind : public IdBase { constexpr IntKind IntKind::Unsigned = IntKind(0); constexpr IntKind IntKind::Signed = IntKind(1); -// A float kind value. +// A float kind value. This describes the semantics of the floating-point type. +// This represents very similar information to the bit-width, but is more +// precise. In particular, there is in general more than one floating-point type +// with a given bit-width, and while only one such type can be named with the +// `fN` notation, the others should still be modeled as `FloatType`s. struct FloatKind : public IdBase { // Not used by `Print`, but for `IdKind`. static constexpr llvm::StringLiteral Label = "float_kind"; + // An explicitly absent kind. Used when the kind has not been determined. + static const FloatKind None; + + // Supported IEEE-754 interchange formats. These correspond to Carbon `fN` + // type literal syntax. + static const FloatKind Binary16; + static const FloatKind Binary32; + static const FloatKind Binary64; + static const FloatKind Binary128; + // Note, binary256 is not supported by LLVM and hence not by us. + + // Other formats supported by LLVM. Support for these may be + // target-dependent. + // TODO: Add a mechanism to use these types from Carbon code. + static const FloatKind BFloat16; + static const FloatKind X87Float80; + static const FloatKind PPCFloat128; + using IdBase::IdBase; - auto Print(llvm::raw_ostream& out) const -> void { out << "float"; } + auto Print(llvm::raw_ostream& out) const -> void; + + // Query the LLVM semantics model associated with this kind of floating-point + // type. This kind must be concrete. + auto Semantics() const -> const llvm::fltSemantics&; }; +constexpr FloatKind FloatKind::None = FloatKind(NoneIndex); + +constexpr FloatKind FloatKind::Binary16 = FloatKind(0); +constexpr FloatKind FloatKind::Binary32 = FloatKind(1); +constexpr FloatKind FloatKind::Binary64 = FloatKind(2); +constexpr FloatKind FloatKind::Binary128 = FloatKind(3); +constexpr FloatKind FloatKind::BFloat16 = FloatKind(4); +constexpr FloatKind FloatKind::X87Float80 = FloatKind(5); +constexpr FloatKind FloatKind::PPCFloat128 = FloatKind(6); + // An X-macro for special names. Uses should look like: // // #define CARBON_SPECIAL_NAME_ID_FOR_XYZ(Name) ... diff --git a/toolchain/sem_ir/typed_insts.h b/toolchain/sem_ir/typed_insts.h index 179305218655..9449d0b6c294 100644 --- a/toolchain/sem_ir/typed_insts.h +++ b/toolchain/sem_ir/typed_insts.h @@ -734,6 +734,7 @@ struct FloatType { // TODO: Consider adding a more compact way of representing either a small // float bit width or an inst_id. InstId bit_width_id; + FloatKind float_kind; }; // A floating point value.