Procházet zdrojové kódy

Switch to representing FloatLiteralType as a RealId. (#5944)

Don't convert to f64 until we know that's the type that we actually
want. Also reimplement the conversion from RealId to FloatId to perform
an exact conversion with a real check for overflow, rather than
performing an approximate conversion via the host `double` type.

Unfortunately, LLVM doesn't expose its integer mantissa and exponent to
APFloat conversion, so we convert the RealId back to a string for now.

The LLVM conversion also detects overflow only if the literal would
round to having an out-of-range exponent, not if the literal is outside
the range of values of the type as the Carbon design expects. It's not
clear to me which rule we actually want here, so for simplicitly I'm
using the LLVM rule for now.

In preparation for adding other floating-point types beyond f64.
Richard Smith před 8 měsíci
rodič
revize
629f77eb61
35 změnil soubory, kde provedl 352 přidání a 380 odebrání
  1. 9 2
      toolchain/base/value_ids.h
  2. 5 0
      toolchain/check/diagnostic_emitter.cpp
  3. 59 4
      toolchain/check/eval.cpp
  4. 2 36
      toolchain/check/handle_literal.cpp
  5. 61 17
      toolchain/check/testdata/basics/numeric_literals.carbon
  6. 3 22
      toolchain/check/testdata/builtins/float/add.carbon
  7. 91 87
      toolchain/check/testdata/builtins/float/convert_checked.carbon
  8. 3 22
      toolchain/check/testdata/builtins/float/div.carbon
  9. 5 30
      toolchain/check/testdata/builtins/float/eq.carbon
  10. 5 30
      toolchain/check/testdata/builtins/float/less_eq.carbon
  11. 3 22
      toolchain/check/testdata/builtins/float/mul.carbon
  12. 3 22
      toolchain/check/testdata/builtins/float/sub.carbon
  13. 2 2
      toolchain/check/testdata/builtins/float_literal/make_type.carbon
  14. 2 2
      toolchain/check/testdata/function/call/fail_param_type.carbon
  15. 4 4
      toolchain/check/testdata/function/call/fail_return_type_mismatch.carbon
  16. 2 2
      toolchain/check/testdata/index/fail_array_non_int_indexing.carbon
  17. 4 4
      toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon
  18. 4 4
      toolchain/check/testdata/interop/cpp/function/param_unsupported.carbon
  19. 2 2
      toolchain/check/testdata/operators/builtin/fail_type_mismatch_assignment.carbon
  20. 2 2
      toolchain/check/testdata/operators/builtin/fail_type_mismatch_once.carbon
  21. 2 2
      toolchain/check/testdata/pointer/fail_address_of_value.carbon
  22. 4 4
      toolchain/check/testdata/return/fail_returned_var_type.carbon
  23. 2 2
      toolchain/check/testdata/return/fail_type_mismatch.carbon
  24. 2 2
      toolchain/check/testdata/struct/fail_field_type_mismatch.carbon
  25. 4 4
      toolchain/check/testdata/struct/fail_member_access_type.carbon
  26. 5 5
      toolchain/check/testdata/struct/member_access.carbon
  27. 1 2
      toolchain/diagnostics/diagnostic_kind.def
  28. 6 10
      toolchain/lower/constant.cpp
  29. 2 2
      toolchain/lower/testdata/array/base.carbon
  30. 20 26
      toolchain/sem_ir/builtin_function_kind.cpp
  31. 1 0
      toolchain/sem_ir/expr_info.cpp
  32. 14 4
      toolchain/sem_ir/inst_fingerprinter.cpp
  33. 1 0
      toolchain/sem_ir/inst_kind.def
  34. 1 0
      toolchain/sem_ir/inst_namer.cpp
  35. 16 1
      toolchain/sem_ir/typed_insts.h

+ 9 - 2
toolchain/base/value_ids.h

@@ -19,8 +19,10 @@ namespace Carbon {
 // This is either a dyadic fraction (mantissa * 2^exponent) or a decadic
 // fraction (mantissa * 10^exponent).
 //
-// These values are not canonicalized, because we don't expect them to repeat
-// and don't use them in SemIR values.
+// These values are not canonicalized, because we don't expect them to repeat.
+// We use RealIds in SemIR::FloatLiteralValues, and this results in all real
+// literals being distinct constants, even if they represent the same value.
+// TODO: Address this by using a different representation in SemIR.
 struct Real : public Printable<Real> {
   auto Print(llvm::raw_ostream& output_stream) const -> void {
     mantissa.print(output_stream, /*isSigned=*/false);
@@ -51,6 +53,11 @@ constexpr FloatId FloatId::None(FloatId::NoneIndex);
 
 // Corresponds to a Real value.
 struct RealId : public IdBase<RealId> {
+  // TODO: We don't use Diagnostics::TypeInfo here for layering reasons.
+  struct DiagnosticType {
+    using StorageType = std::string;
+  };
+
   static constexpr llvm::StringLiteral Label = "real";
   static const RealId None;
   using IdBase::IdBase;

+ 5 - 0
toolchain/check/diagnostic_emitter.cpp

@@ -122,6 +122,11 @@ auto DiagnosticEmitter::ConvertArg(llvm::Any arg) const -> llvm::Any {
     return llvm::APSInt(typed_int->value,
                         !sem_ir_->types().IsSignedInt(typed_int->type));
   }
+  if (auto* real_id = llvm::any_cast<RealId>(&arg)) {
+    RawStringOstream out;
+    sem_ir_->reals().Get(*real_id).Print(out);
+    return out.TakeStr();
+  }
   if (auto* specific_interface_id =
           llvm::any_cast<SemIR::SpecificInterfaceId>(&arg)) {
     auto specific_interface =

+ 59 - 4
toolchain/check/eval.cpp

@@ -9,6 +9,7 @@
 #include <optional>
 #include <utility>
 
+#include "common/raw_string_ostream.h"
 #include "llvm/Support/ConvertUTF.h"
 #include "toolchain/base/canonical_value_store.h"
 #include "toolchain/base/kind_switch.h"
@@ -1073,14 +1074,68 @@ static auto PerformCheckedIntConvert(Context& context, SemIR::LocId loc_id,
 
 // Performs a conversion between floating-point types, diagnosing if the value
 // doesn't fit in the destination type.
-static auto PerformCheckedFloatConvert(Context& context,
-                                       SemIR::LocId /*loc_id*/,
+static auto PerformCheckedFloatConvert(Context& context, SemIR::LocId loc_id,
                                        SemIR::InstId arg_id,
                                        SemIR::TypeId dest_type_id)
     -> SemIR::ConstantId {
+  if (auto literal =
+          context.insts().TryGetAs<SemIR::FloatLiteralValue>(arg_id)) {
+    if (context.types().Is<SemIR::FloatLiteralType>(dest_type_id)) {
+      return MakeConstantResult(
+          context,
+          SemIR::FloatLiteralValue{.type_id = dest_type_id,
+                                   .real_id = literal->real_id},
+          Phase::Concrete);
+    }
+
+    // Convert the real literal to an llvm::APFloat and add it to the floats
+    // ValueStore. In the future this would use an arbitrary precision Rational
+    // type.
+    //
+    // TODO: Implement Carbon's actual implicit conversion rules for
+    // floating-point constants, as per the design
+    // docs/design/expressions/implicit_conversions.md
+    auto real_value = context.sem_ir().reals().Get(literal->real_id);
+
+    // Convert the real value to a string.
+    llvm::SmallString<64> str;
+    real_value.mantissa.toString(str, real_value.is_decimal ? 10 : 16,
+                                 /*signed=*/false, /*formatAsCLiteral=*/true);
+    str += real_value.is_decimal ? "e" : "p";
+    real_value.exponent.toStringSigned(str);
+
+    // Convert the string to an APFloat.
+    // TODO: Compute the fltSemantics from the type.
+    llvm::APFloat result(llvm::APFloat::IEEEdouble());
+    // 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
+    // public API.
+    auto status =
+        result.convertFromString(str, llvm::APFloat::rmNearestTiesToEven);
+    if (auto error = status.takeError()) {
+      // The literal we create should always successfully parse.
+      CARBON_FATAL("Float literal parsing failed: {0}",
+                   toString(std::move(error)));
+    }
+    if (status.get() & llvm::APFloat::opOverflow) {
+      CARBON_DIAGNOSTIC(FloatTooLargeForType, 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);
+      return SemIR::ErrorInst::ConstantId;
+    }
+    return MakeFloatResult(context, dest_type_id, std::move(result));
+  }
+
+  // TODO: Perform a conversion if necessary.
+  if (context.types().Is<SemIR::FloatLiteralType>(dest_type_id)) {
+    context.TODO(loc_id, "conversion from float to float literal");
+    return SemIR::ErrorInst::ConstantId;
+  }
+
   auto arg = context.insts().GetAs<SemIR::FloatValue>(arg_id);
-  // TODO: Perform a conversion if necessary. For now, all FloatValues are
-  // represented as double-precision APFloats, so no conversion is needed.
   return MakeConstantResult(
       context,
       SemIR::FloatValue{.type_id = dest_type_id, .float_id = arg.float_id},

+ 2 - 36
toolchain/check/handle_literal.cpp

@@ -55,47 +55,13 @@ auto HandleParseNode(Context& context, Parse::IntLiteralId node_id) -> bool {
 }
 
 auto HandleParseNode(Context& context, Parse::RealLiteralId node_id) -> bool {
-  // Convert the real literal to an llvm::APFloat and add it to the floats
-  // ValueStore. In the future this would use an arbitrary precision Rational
-  // type.
-  //
-  // TODO: Implement Carbon's actual implicit conversion rules for
-  // floating-point constants, as per the design
-  // docs/design/expressions/implicit_conversions.md
   auto real_id =
       context.tokens().GetRealLiteral(context.parse_tree().node_token(node_id));
-  auto real_value = context.sem_ir().reals().Get(real_id);
-
-  if (real_value.mantissa.getActiveBits() > 64) {
-    CARBON_DIAGNOSTIC(RealMantissaTooLargeForI64, Error,
-                      "real mantissa with value {0} does not fit in i64",
-                      llvm::APSInt);
-    context.emitter().Emit(node_id, RealMantissaTooLargeForI64,
-                           llvm::APSInt(real_value.mantissa, true));
-    context.node_stack().Push(node_id, SemIR::ErrorInst::InstId);
-    return true;
-  }
-
-  if (real_value.exponent.getSignificantBits() > 64) {
-    CARBON_DIAGNOSTIC(RealExponentTooLargeForI64, Error,
-                      "real exponent with value {0} does not fit in i64",
-                      llvm::APSInt);
-    context.emitter().Emit(node_id, RealExponentTooLargeForI64,
-                           llvm::APSInt(real_value.exponent, false));
-    context.node_stack().Push(node_id, SemIR::ErrorInst::InstId);
-    return true;
-  }
-
-  double double_val = real_value.mantissa.getZExtValue() *
-                      std::pow((real_value.is_decimal ? 10 : 2),
-                               real_value.exponent.getSExtValue());
-
-  auto float_id = context.sem_ir().floats().Add(llvm::APFloat(double_val));
-  AddInstAndPush<SemIR::FloatValue>(
+  AddInstAndPush<SemIR::FloatLiteralValue>(
       context, node_id,
       {.type_id =
            GetSingletonType(context, SemIR::FloatLiteralType::TypeInstId),
-       .float_id = float_id});
+       .real_id = real_id});
   return true;
 }
 

+ 61 - 17
toolchain/check/testdata/basics/numeric_literals.carbon

@@ -69,21 +69,65 @@ library "[[@TEST_NAME]]";
 // CHECK:STDERR:
 let c: i32 = 0x8000_0000;
 
+// --- very_large_mantissa.carbon
+
+library "[[@TEST_NAME]]";
+
+let large: f64 = 99999999999999999999999999999999999999999999999999999999999999999999999.0e237;
+let max_trunc: f64 = 17976931348623157081452742373170435679807056752584499659891747680315726.0e238;
+let max: f64 = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0;
+
+let max_hex: f64 = 0x1.FFFFFFFFFFFFFp+1023;
+
+// The largest number that wouldn't round to have an out-of-bounds exponent.
+// This is 2^1024 - 2^54 - epsilon.
+// TODO: The design says that we should treat this as an error. Decide if that's
+// right or if we want to round before checking for overflow.
+let max_rounds_down: f64 = 179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.9999999999999;
+let max_rounds_down_trunc: f64 = 17976931348623158079372897140530341507993413271003782693617377898044496.8e238;
+
+let max_rounds_down_hex: f64 = 0x1.FFFFFFFFFFFFF7FFFFFFFFFFp+1023;
+
 // --- fail_overflow_very_large_mantissa.carbon
 
 library "[[@TEST_NAME]]";
 
-// CHECK:STDERR: fail_overflow_very_large_mantissa.carbon:[[@LINE+4]]:14: error: real mantissa with value 399999999999999999930 does not fit in i64 [RealMantissaTooLargeForI64]
-// CHECK:STDERR: let d: f64 = 39999999999999999993.0e3;
-// CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~~~~~~~
+// 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: let too_large: f64 = 39999999999999999999999999999999999999999999999999999999999999999999999.0e238;
+// CHECK:STDERR:                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+let too_large: f64 = 39999999999999999999999999999999999999999999999999999999999999999999999.0e238;
+
+// TODO: These are larger than DBL_MAX but would still round to DBL_MAX if f64
+// had a wider exponent field. The design says these are invalid.
+let above_max_trunc: f64 = 17976931348623157081452742373170435679807056752584499659891747680315727.0e238;
+let max_plus_one: f64 = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858369.0;
+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: 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: 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: let min_rounds_to_inf_hex: f64 = 0x1.FFFFFFFFFFFFF8p+1023;
+// CHECK:STDERR:                                  ^~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-let d: f64 = 39999999999999999993.0e3;
+let min_rounds_to_inf_hex: f64 = 0x1.FFFFFFFFFFFFF8p+1023;
 
 // --- fail_overflow_very_large_exponent.carbon
 
 library "[[@TEST_NAME]]";
 
-// CHECK:STDERR: fail_overflow_very_large_exponent.carbon:[[@LINE+4]]:14: error: real exponent with value 39999999999999999992 does not fit in i64 [RealExponentTooLargeForI64]
+// 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: let e: f64 = 5.0e39999999999999999993;
 // CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
@@ -95,12 +139,12 @@ let e: f64 = 5.0e39999999999999999993;
 // CHECK:STDOUT:   %int_8.b85: Core.IntLiteral = int_value 8 [concrete]
 // CHECK:STDOUT:   %int_9.988: Core.IntLiteral = int_value 9 [concrete]
 // CHECK:STDOUT:   %int_2147483647.d89: Core.IntLiteral = int_value 2147483647 [concrete]
-// CHECK:STDOUT:   %float.8ca: Core.FloatLiteral = float_value 0.90000000000000002 [concrete]
-// CHECK:STDOUT:   %float.fde: Core.FloatLiteral = float_value 8 [concrete]
-// CHECK:STDOUT:   %float.7a6: Core.FloatLiteral = float_value 80 [concrete]
-// CHECK:STDOUT:   %float.23b: Core.FloatLiteral = float_value 1.0E+7 [concrete]
-// CHECK:STDOUT:   %float.b98: Core.FloatLiteral = float_value 1.0E+8 [concrete]
-// CHECK:STDOUT:   %float.34d: Core.FloatLiteral = float_value 1.0E-8 [concrete]
+// CHECK:STDOUT:   %float.7d0: Core.FloatLiteral = float_literal_value 9e-1 [concrete]
+// CHECK:STDOUT:   %float.4bc: Core.FloatLiteral = float_literal_value 80e-1 [concrete]
+// CHECK:STDOUT:   %float.24e: Core.FloatLiteral = float_literal_value 800e-1 [concrete]
+// CHECK:STDOUT:   %float.4d9: Core.FloatLiteral = float_literal_value 10e6 [concrete]
+// CHECK:STDOUT:   %float.150: Core.FloatLiteral = float_literal_value 10e7 [concrete]
+// CHECK:STDOUT:   %float.07e: Core.FloatLiteral = float_literal_value 10e-9 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -116,12 +160,12 @@ let e: f64 = 5.0e39999999999999999993;
 // CHECK:STDOUT:   %int_2147483647.loc13: Core.IntLiteral = int_value 2147483647 [concrete = constants.%int_2147483647.d89]
 // CHECK:STDOUT:   %int_2147483647.loc14: Core.IntLiteral = int_value 2147483647 [concrete = constants.%int_2147483647.d89]
 // CHECK:STDOUT:   <elided>
-// CHECK:STDOUT:   %float.loc19: Core.FloatLiteral = float_value 0.90000000000000002 [concrete = constants.%float.8ca]
-// CHECK:STDOUT:   %float.loc20: Core.FloatLiteral = float_value 8 [concrete = constants.%float.fde]
-// CHECK:STDOUT:   %float.loc21: Core.FloatLiteral = float_value 80 [concrete = constants.%float.7a6]
-// CHECK:STDOUT:   %float.loc22: Core.FloatLiteral = float_value 1.0E+7 [concrete = constants.%float.23b]
-// CHECK:STDOUT:   %float.loc23: Core.FloatLiteral = float_value 1.0E+8 [concrete = constants.%float.b98]
-// CHECK:STDOUT:   %float.loc24: Core.FloatLiteral = float_value 1.0E-8 [concrete = constants.%float.34d]
+// CHECK:STDOUT:   %float.loc19: Core.FloatLiteral = float_literal_value 9e-1 [concrete = constants.%float.7d0]
+// CHECK:STDOUT:   %float.loc20: Core.FloatLiteral = float_literal_value 80e-1 [concrete = constants.%float.4bc]
+// CHECK:STDOUT:   %float.loc21: Core.FloatLiteral = float_literal_value 800e-1 [concrete = constants.%float.24e]
+// CHECK:STDOUT:   %float.loc22: Core.FloatLiteral = float_literal_value 10e6 [concrete = constants.%float.4d9]
+// CHECK:STDOUT:   %float.loc23: Core.FloatLiteral = float_literal_value 10e7 [concrete = constants.%float.150]
+// CHECK:STDOUT:   %float.loc24: Core.FloatLiteral = float_literal_value 10e-9 [concrete = constants.%float.07e]
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 3 - 22
toolchain/check/testdata/builtins/float/add.carbon

@@ -57,35 +57,16 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
   return BadReturnType(a, b);
 }
 
-// --- literal.carbon
+// --- fail_literal.carbon
 
 library "[[@TEST_NAME]]";
 
 fn Literal() -> type = "float_literal.make_type";
-fn AddLiteral(a: Literal(), b: Literal()) -> Literal() = "float.add";
-
-// --- literal_comptime.carbon
-
-library "[[@TEST_NAME]]";
-import library "literal";
-
-let n: Literal() = AddLiteral(1.0, 2.0);
-
-// --- fail_literal_runtime.carbon
-
-library "[[@TEST_NAME]]";
-import library "literal";
-
-var m: Literal();
-// CHECK:STDERR: fail_literal_runtime.carbon:[[@LINE+8]]:20: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]
-// CHECK:STDERR: let n: Literal() = AddLiteral(1.0, m);
-// CHECK:STDERR:                    ^~~~~~~~~~~~~~~~~~
-// CHECK:STDERR: fail_literal_runtime.carbon:[[@LINE-6]]:1: in import [InImport]
-// CHECK:STDERR: literal.carbon:5:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]
+// CHECK:STDERR: fail_literal.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.add" [InvalidBuiltinSignature]
 // CHECK:STDERR: fn AddLiteral(a: Literal(), b: Literal()) -> Literal() = "float.add";
 // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-let n: Literal() = AddLiteral(1.0, m);
+fn AddLiteral(a: Literal(), b: Literal()) -> Literal() = "float.add";
 
 // CHECK:STDOUT: --- float_add.carbon
 // CHECK:STDOUT:

+ 91 - 87
toolchain/check/testdata/builtins/float/convert_checked.carbon

@@ -168,6 +168,10 @@ import library "f64";
 // CHECK:STDERR:
 let a: f32 = Float64ToFloat32(1.0e39);
 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: let c: f64 = FloatLiteralToFloat64(1.0e309);
+// CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
 let c: f64 = FloatLiteralToFloat64(1.0e309);
 //@dump-sem-ir-end
 
@@ -207,7 +211,7 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT:   %pattern_type.dab: type = pattern_type Core.FloatLiteral [concrete]
 // CHECK:STDOUT:   %FloatLiteralToFloatLiteral.type: type = fn_type @FloatLiteralToFloatLiteral [concrete]
 // CHECK:STDOUT:   %FloatLiteralToFloatLiteral: %FloatLiteralToFloatLiteral.type = struct_value () [concrete]
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -233,7 +237,7 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %FloatLiteralToFloatLiteral.ref: %FloatLiteralToFloatLiteral.type = name_ref FloatLiteralToFloatLiteral, imports.%Main.FloatLiteralToFloatLiteral [concrete = constants.%FloatLiteralToFloatLiteral]
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float]
 // CHECK:STDOUT:   %FloatLiteralToFloatLiteral.call: init Core.FloatLiteral = call %FloatLiteralToFloatLiteral.ref(%float) [concrete = constants.%float]
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
@@ -246,11 +250,11 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]
 // CHECK:STDOUT:   %FloatLiteralToFloat64.type: type = fn_type @FloatLiteralToFloat64 [concrete]
 // CHECK:STDOUT:   %FloatLiteralToFloat64: %FloatLiteralToFloat64.type = struct_value () [concrete]
-// CHECK:STDOUT:   %float.be6: Core.FloatLiteral = float_value 0 [concrete]
+// CHECK:STDOUT:   %float.1f7: Core.FloatLiteral = float_literal_value 0e-1 [concrete]
 // CHECK:STDOUT:   %float.0a8: %f64.d77 = float_value 0 [concrete]
-// CHECK:STDOUT:   %float.a31: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %float.674: Core.FloatLiteral = float_literal_value 10e-1 [concrete]
 // CHECK:STDOUT:   %float.d20: %f64.d77 = float_value 1 [concrete]
-// CHECK:STDOUT:   %float.9a4: Core.FloatLiteral = float_value 1.0E+308 [concrete]
+// CHECK:STDOUT:   %float.173: Core.FloatLiteral = float_literal_value 10e307 [concrete]
 // CHECK:STDOUT:   %float.bde: %f64.d77 = float_value 1.0E+308 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -294,13 +298,13 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %FloatLiteralToFloat64.ref.loc6: %FloatLiteralToFloat64.type = name_ref FloatLiteralToFloat64, imports.%Main.FloatLiteralToFloat64 [concrete = constants.%FloatLiteralToFloat64]
-// CHECK:STDOUT:   %float.loc6: Core.FloatLiteral = float_value 0 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %float.loc6: Core.FloatLiteral = float_literal_value 0e-1 [concrete = constants.%float.1f7]
 // CHECK:STDOUT:   %FloatLiteralToFloat64.call.loc6: init %f64.d77 = call %FloatLiteralToFloat64.ref.loc6(%float.loc6) [concrete = constants.%float.0a8]
 // CHECK:STDOUT:   %FloatLiteralToFloat64.ref.loc7: %FloatLiteralToFloat64.type = name_ref FloatLiteralToFloat64, imports.%Main.FloatLiteralToFloat64 [concrete = constants.%FloatLiteralToFloat64]
-// CHECK:STDOUT:   %float.loc7: Core.FloatLiteral = float_value 1 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %float.loc7: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float.674]
 // CHECK:STDOUT:   %FloatLiteralToFloat64.call.loc7: init %f64.d77 = call %FloatLiteralToFloat64.ref.loc7(%float.loc7) [concrete = constants.%float.d20]
 // CHECK:STDOUT:   %FloatLiteralToFloat64.ref.loc8: %FloatLiteralToFloat64.type = name_ref FloatLiteralToFloat64, imports.%Main.FloatLiteralToFloat64 [concrete = constants.%FloatLiteralToFloat64]
-// CHECK:STDOUT:   %float.loc8: Core.FloatLiteral = float_value 1.0E+308 [concrete = constants.%float.9a4]
+// CHECK:STDOUT:   %float.loc8: Core.FloatLiteral = float_literal_value 10e307 [concrete = constants.%float.173]
 // CHECK:STDOUT:   %FloatLiteralToFloat64.call.loc8: init %f64.d77 = call %FloatLiteralToFloat64.ref.loc8(%float.loc8) [concrete = constants.%float.bde]
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
@@ -313,9 +317,9 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT:   %pattern_type.201: type = pattern_type %f32 [concrete]
 // CHECK:STDOUT:   %FloatLiteralToFloat32.type: type = fn_type @FloatLiteralToFloat32 [concrete]
 // CHECK:STDOUT:   %FloatLiteralToFloat32: %FloatLiteralToFloat32.type = struct_value () [concrete]
-// CHECK:STDOUT:   %float.be6: Core.FloatLiteral = float_value 0 [concrete]
-// CHECK:STDOUT:   %float.a31: Core.FloatLiteral = float_value 1 [concrete]
-// CHECK:STDOUT:   %float.cf6: Core.FloatLiteral = float_value 9.9999999999999997E+37 [concrete]
+// CHECK:STDOUT:   %float.1f7: Core.FloatLiteral = float_literal_value 0e-1 [concrete]
+// CHECK:STDOUT:   %float.674: Core.FloatLiteral = float_literal_value 10e-1 [concrete]
+// CHECK:STDOUT:   %float.516: Core.FloatLiteral = float_literal_value 10e37 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -358,13 +362,13 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // 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_value 0 [concrete = constants.%float.be6]
+// 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_value 1 [concrete = constants.%float.a31]
+// 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_value 9.9999999999999997E+37 [concrete = constants.%float.cf6]
+// 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:   <elided>
 // CHECK:STDOUT: }
@@ -377,7 +381,7 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]
 // CHECK:STDOUT:   %Float64ToFloat64.type: type = fn_type @Float64ToFloat64 [concrete]
 // CHECK:STDOUT:   %Float64ToFloat64: %Float64ToFloat64.type = struct_value () [concrete]
-// CHECK:STDOUT:   %float.be6: Core.FloatLiteral = float_value 0 [concrete]
+// CHECK:STDOUT:   %float.1f7: Core.FloatLiteral = float_literal_value 0e-1 [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.6ec: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]
 // CHECK:STDOUT:   %ImplicitAs.Convert.type.726: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f64.d77) [concrete]
 // CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
@@ -388,17 +392,17 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf = struct_value () [concrete]
 // CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.6ec = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.857) [concrete]
 // CHECK:STDOUT:   %.678: type = fn_type_with_self_type %ImplicitAs.Convert.type.726, %ImplicitAs.facet [concrete]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.93b: <bound method> = bound_method %float.be6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.057: <bound method> = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]
-// CHECK:STDOUT:   %bound_method.71f: <bound method> = bound_method %float.be6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %bound_method.728: <bound method> = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %float.0a8: %f64.d77 = float_value 0 [concrete]
-// CHECK:STDOUT:   %float.a31: Core.FloatLiteral = float_value 1 [concrete]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.64b: <bound method> = bound_method %float.a31, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
-// CHECK:STDOUT:   %bound_method.20c: <bound method> = bound_method %float.a31, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %float.674: Core.FloatLiteral = float_literal_value 10e-1 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.510: <bound method> = bound_method %float.674, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %bound_method.3e8: <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.9a4: Core.FloatLiteral = float_value 1.0E+308 [concrete]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.260: <bound method> = bound_method %float.9a4, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
-// CHECK:STDOUT:   %bound_method.aa0: <bound method> = bound_method %float.9a4, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %float.173: Core.FloatLiteral = float_literal_value 10e307 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.1a0: <bound method> = bound_method %float.173, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %bound_method.59e: <bound method> = bound_method %float.173, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %float.bde: %f64.d77 = float_value 1.0E+308 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -444,31 +448,31 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Float64ToFloat64.ref.loc6: %Float64ToFloat64.type = name_ref Float64ToFloat64, imports.%Main.Float64ToFloat64 [concrete = constants.%Float64ToFloat64]
-// CHECK:STDOUT:   %float.loc6: Core.FloatLiteral = float_value 0 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %float.loc6: Core.FloatLiteral = float_literal_value 0e-1 [concrete = constants.%float.1f7]
 // CHECK:STDOUT:   %impl.elem0.loc6: %.678 = impl_witness_access constants.%ImplicitAs.impl_witness.857, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03]
-// CHECK:STDOUT:   %bound_method.loc6_31.1: <bound method> = bound_method %float.loc6, %impl.elem0.loc6 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.93b]
+// CHECK:STDOUT:   %bound_method.loc6_31.1: <bound method> = bound_method %float.loc6, %impl.elem0.loc6 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.057]
 // CHECK:STDOUT:   %specific_fn.loc6: <specific function> = specific_function %impl.elem0.loc6, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc6_31.2: <bound method> = bound_method %float.loc6, %specific_fn.loc6 [concrete = constants.%bound_method.71f]
+// CHECK:STDOUT:   %bound_method.loc6_31.2: <bound method> = bound_method %float.loc6, %specific_fn.loc6 [concrete = constants.%bound_method.728]
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6: init %f64.d77 = call %bound_method.loc6_31.2(%float.loc6) [concrete = constants.%float.0a8]
 // CHECK:STDOUT:   %.loc6_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6 [concrete = constants.%float.0a8]
 // CHECK:STDOUT:   %.loc6_31.2: %f64.d77 = converted %float.loc6, %.loc6_31.1 [concrete = constants.%float.0a8]
 // CHECK:STDOUT:   %Float64ToFloat64.call.loc6: init %f64.d77 = call %Float64ToFloat64.ref.loc6(%.loc6_31.2) [concrete = constants.%float.0a8]
 // CHECK:STDOUT:   %Float64ToFloat64.ref.loc7: %Float64ToFloat64.type = name_ref Float64ToFloat64, imports.%Main.Float64ToFloat64 [concrete = constants.%Float64ToFloat64]
-// CHECK:STDOUT:   %float.loc7: Core.FloatLiteral = float_value 1 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %float.loc7: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float.674]
 // CHECK:STDOUT:   %impl.elem0.loc7: %.678 = impl_witness_access constants.%ImplicitAs.impl_witness.857, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03]
-// CHECK:STDOUT:   %bound_method.loc7_31.1: <bound method> = bound_method %float.loc7, %impl.elem0.loc7 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.64b]
+// CHECK:STDOUT:   %bound_method.loc7_31.1: <bound method> = bound_method %float.loc7, %impl.elem0.loc7 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.510]
 // CHECK:STDOUT:   %specific_fn.loc7: <specific function> = specific_function %impl.elem0.loc7, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc7_31.2: <bound method> = bound_method %float.loc7, %specific_fn.loc7 [concrete = constants.%bound_method.20c]
+// CHECK:STDOUT:   %bound_method.loc7_31.2: <bound method> = bound_method %float.loc7, %specific_fn.loc7 [concrete = constants.%bound_method.3e8]
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7: init %f64.d77 = call %bound_method.loc7_31.2(%float.loc7) [concrete = constants.%float.d20]
 // CHECK:STDOUT:   %.loc7_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7 [concrete = constants.%float.d20]
 // CHECK:STDOUT:   %.loc7_31.2: %f64.d77 = converted %float.loc7, %.loc7_31.1 [concrete = constants.%float.d20]
 // CHECK:STDOUT:   %Float64ToFloat64.call.loc7: init %f64.d77 = call %Float64ToFloat64.ref.loc7(%.loc7_31.2) [concrete = constants.%float.d20]
 // CHECK:STDOUT:   %Float64ToFloat64.ref.loc8: %Float64ToFloat64.type = name_ref Float64ToFloat64, imports.%Main.Float64ToFloat64 [concrete = constants.%Float64ToFloat64]
-// CHECK:STDOUT:   %float.loc8: Core.FloatLiteral = float_value 1.0E+308 [concrete = constants.%float.9a4]
+// CHECK:STDOUT:   %float.loc8: Core.FloatLiteral = float_literal_value 10e307 [concrete = constants.%float.173]
 // CHECK:STDOUT:   %impl.elem0.loc8: %.678 = impl_witness_access constants.%ImplicitAs.impl_witness.857, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03]
-// CHECK:STDOUT:   %bound_method.loc8_31.1: <bound method> = bound_method %float.loc8, %impl.elem0.loc8 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.260]
+// CHECK:STDOUT:   %bound_method.loc8_31.1: <bound method> = bound_method %float.loc8, %impl.elem0.loc8 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.1a0]
 // CHECK:STDOUT:   %specific_fn.loc8: <specific function> = specific_function %impl.elem0.loc8, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc8_31.2: <bound method> = bound_method %float.loc8, %specific_fn.loc8 [concrete = constants.%bound_method.aa0]
+// CHECK:STDOUT:   %bound_method.loc8_31.2: <bound method> = bound_method %float.loc8, %specific_fn.loc8 [concrete = constants.%bound_method.59e]
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc8: init %f64.d77 = call %bound_method.loc8_31.2(%float.loc8) [concrete = constants.%float.bde]
 // CHECK:STDOUT:   %.loc8_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc8 [concrete = constants.%float.bde]
 // CHECK:STDOUT:   %.loc8_31.2: %f64.d77 = converted %float.loc8, %.loc8_31.1 [concrete = constants.%float.bde]
@@ -484,7 +488,7 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT:   %pattern_type.201: type = pattern_type %f32 [concrete]
 // CHECK:STDOUT:   %Float32ToFloat32.type: type = fn_type @Float32ToFloat32 [concrete]
 // CHECK:STDOUT:   %Float32ToFloat32: %Float32ToFloat32.type = struct_value () [concrete]
-// CHECK:STDOUT:   %float.be6: Core.FloatLiteral = float_value 0 [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:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
@@ -495,17 +499,17 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.43b = struct_value () [concrete]
 // CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.31d = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.e3f) [concrete]
 // CHECK:STDOUT:   %.a5d: type = fn_type_with_self_type %ImplicitAs.Convert.type.b8c, %ImplicitAs.facet [concrete]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.02c: <bound method> = bound_method %float.be6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.b37: <bound method> = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete]
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]
-// CHECK:STDOUT:   %bound_method.a33: <bound method> = bound_method %float.be6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %bound_method.91e: <bound method> = 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.a31: Core.FloatLiteral = float_value 1 [concrete]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.bcb: <bound method> = bound_method %float.a31, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete]
-// CHECK:STDOUT:   %bound_method.495: <bound method> = bound_method %float.a31, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [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> = bound_method %float.674, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete]
+// CHECK:STDOUT:   %bound_method.6b4: <bound method> = 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.cf6: Core.FloatLiteral = float_value 9.9999999999999997E+37 [concrete]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.82a: <bound method> = bound_method %float.cf6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete]
-// CHECK:STDOUT:   %bound_method.492: <bound method> = bound_method %float.cf6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %float.516: Core.FloatLiteral = float_literal_value 10e37 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.dc9: <bound method> = bound_method %float.516, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete]
+// CHECK:STDOUT:   %bound_method.3b8: <bound method> = 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: }
 // CHECK:STDOUT:
@@ -551,31 +555,31 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // 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_value 0 [concrete = constants.%float.be6]
+// 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> = bound_method %float.loc13, %impl.elem0.loc13 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.02c]
+// CHECK:STDOUT:   %bound_method.loc13_31.1: <bound method> = bound_method %float.loc13, %impl.elem0.loc13 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.b37]
 // CHECK:STDOUT:   %specific_fn.loc13: <specific function> = 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> = bound_method %float.loc13, %specific_fn.loc13 [concrete = constants.%bound_method.a33]
+// CHECK:STDOUT:   %bound_method.loc13_31.2: <bound method> = 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_value 1 [concrete = constants.%float.a31]
+// 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> = bound_method %float.loc14, %impl.elem0.loc14 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.bcb]
+// CHECK:STDOUT:   %bound_method.loc14_31.1: <bound method> = bound_method %float.loc14, %impl.elem0.loc14 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.6d0]
 // CHECK:STDOUT:   %specific_fn.loc14: <specific function> = 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> = bound_method %float.loc14, %specific_fn.loc14 [concrete = constants.%bound_method.495]
+// CHECK:STDOUT:   %bound_method.loc14_31.2: <bound method> = 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_value 9.9999999999999997E+37 [concrete = constants.%float.cf6]
+// 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> = bound_method %float.loc15, %impl.elem0.loc15 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.82a]
+// CHECK:STDOUT:   %bound_method.loc15_31.1: <bound method> = bound_method %float.loc15, %impl.elem0.loc15 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.dc9]
 // CHECK:STDOUT:   %specific_fn.loc15: <specific function> = 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> = bound_method %float.loc15, %specific_fn.loc15 [concrete = constants.%bound_method.492]
+// CHECK:STDOUT:   %bound_method.loc15_31.2: <bound method> = 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]
@@ -593,7 +597,7 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT:   %Float64ToFloat32: %Float64ToFloat32.type = struct_value () [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:   %float.a31: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %float.674: Core.FloatLiteral = float_literal_value 10e-1 [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.6ec: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]
 // CHECK:STDOUT:   %ImplicitAs.Convert.type.726: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f64.d77) [concrete]
 // CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
@@ -604,9 +608,9 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf = struct_value () [concrete]
 // CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.6ec = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.857) [concrete]
 // CHECK:STDOUT:   %.678: type = fn_type_with_self_type %ImplicitAs.Convert.type.726, %ImplicitAs.facet [concrete]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.a31, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.674, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.a31, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %bound_method: <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: }
 // CHECK:STDOUT:
@@ -632,7 +636,7 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // 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: Core.FloatLiteral = float_value 1 [concrete = constants.%float.a31]
+// 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> = bound_method %float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]
 // CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
@@ -655,7 +659,7 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // 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:   %float.629: Core.FloatLiteral = float_value 9.9999999999999994E+38 [concrete]
+// CHECK:STDOUT:   %float.bfd691.1: Core.FloatLiteral = float_literal_value 10e38 [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.6ec: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]
 // CHECK:STDOUT:   %ImplicitAs.Convert.type.726: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f64.d77) [concrete]
 // CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
@@ -666,16 +670,16 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf = struct_value () [concrete]
 // CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.6ec = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.857) [concrete]
 // CHECK:STDOUT:   %.678: type = fn_type_with_self_type %ImplicitAs.Convert.type.726, %ImplicitAs.facet [concrete]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.629, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.bfd691.1, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.629, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.bfd691.1, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %float.c37: %f64.d77 = float_value 9.9999999999999994E+38 [concrete]
 // CHECK:STDOUT:   %FloatLiteralToFloat32.type: type = fn_type @FloatLiteralToFloat32 [concrete]
 // CHECK:STDOUT:   %FloatLiteralToFloat32: %FloatLiteralToFloat32.type = struct_value () [concrete]
+// CHECK:STDOUT:   %float.bfd691.2: Core.FloatLiteral = float_literal_value 10e38 [concrete]
 // CHECK:STDOUT:   %FloatLiteralToFloat64.type: type = fn_type @FloatLiteralToFloat64 [concrete]
 // CHECK:STDOUT:   %FloatLiteralToFloat64: %FloatLiteralToFloat64.type = struct_value () [concrete]
-// CHECK:STDOUT:   %float.669: Core.FloatLiteral = float_value +Inf [concrete]
-// CHECK:STDOUT:   %float.181: %f64.d77 = float_value +Inf [concrete]
+// CHECK:STDOUT:   %float.bb5: Core.FloatLiteral = float_literal_value 10e308 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -710,19 +714,19 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT:   name_binding_decl {
 // CHECK:STDOUT:     %c.patt: %pattern_type.0ae = binding_pattern c [concrete]
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.loc18_8: type = splice_block %f64 [concrete = constants.%f64.d77] {
+// CHECK:STDOUT:   %.loc22_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:   %.loc18_43.1: %f64.d77 = value_of_initializer @__global_init.%FloatLiteralToFloat64.call [concrete = constants.%float.181]
-// CHECK:STDOUT:   %.loc18_43.2: %f64.d77 = converted @__global_init.%FloatLiteralToFloat64.call, %.loc18_43.1 [concrete = constants.%float.181]
-// CHECK:STDOUT:   %c: %f64.d77 = bind_name c, %.loc18_43.2
+// CHECK:STDOUT:   %.loc22_43.1: %f64.d77 = value_of_initializer @__global_init.%FloatLiteralToFloat64.call [concrete = <error>]
+// CHECK:STDOUT:   %.loc22_43.2: %f64.d77 = converted @__global_init.%FloatLiteralToFloat64.call, %.loc22_43.1 [concrete = <error>]
+// CHECK:STDOUT:   %c: %f64.d77 = bind_name c, %.loc22_43.2 [concrete = <error>]
 // 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_value 9.9999999999999994E+38 [concrete = constants.%float.629]
+// CHECK:STDOUT:   %float.loc16: 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> = bound_method %float.loc16, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]
 // CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
@@ -732,11 +736,11 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // 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:   %FloatLiteralToFloat32.ref: %FloatLiteralToFloat32.type = name_ref FloatLiteralToFloat32, imports.%Main.FloatLiteralToFloat32 [concrete = constants.%FloatLiteralToFloat32]
-// CHECK:STDOUT:   %float.loc17: Core.FloatLiteral = float_value 9.9999999999999994E+38 [concrete = constants.%float.629]
+// 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:   %FloatLiteralToFloat64.ref: %FloatLiteralToFloat64.type = name_ref FloatLiteralToFloat64, imports.%Main.FloatLiteralToFloat64 [concrete = constants.%FloatLiteralToFloat64]
-// CHECK:STDOUT:   %float.loc18: Core.FloatLiteral = float_value +Inf [concrete = constants.%float.669]
-// CHECK:STDOUT:   %FloatLiteralToFloat64.call: init %f64.d77 = call %FloatLiteralToFloat64.ref(%float.loc18) [concrete = constants.%float.181]
+// 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 = <error>]
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -750,7 +754,7 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // 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:   %float.a31: Core.FloatLiteral = float_value 1 [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:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
@@ -761,14 +765,14 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.43b = struct_value () [concrete]
 // CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.31d = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.e3f) [concrete]
 // CHECK:STDOUT:   %.a5d: type = fn_type_with_self_type %ImplicitAs.Convert.type.b8c, %ImplicitAs.facet [concrete]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.bcb: <bound method> = bound_method %float.a31, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.6d0: <bound method> = bound_method %float.674, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete]
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]
-// CHECK:STDOUT:   %bound_method.495: <bound method> = bound_method %float.a31, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %bound_method.6b4: <bound method> = 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.f26: Core.FloatLiteral = float_value 9.9999999999999988E+29 [concrete]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.6ef: <bound method> = bound_method %float.f26, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete]
-// CHECK:STDOUT:   %bound_method.f39: <bound method> = bound_method %float.f26, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
-// CHECK:STDOUT:   %float.2d0: %f32 = float_value 9.9999999999999988E+29 [concrete]
+// CHECK:STDOUT:   %float.9bd: Core.FloatLiteral = float_literal_value 10e29 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.a5c: <bound method> = bound_method %float.9bd, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1a3 [concrete]
+// CHECK:STDOUT:   %bound_method.3e4: <bound method> = 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: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -803,24 +807,24 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Float32ToFloat64.ref.loc6: %Float32ToFloat64.type = name_ref Float32ToFloat64, imports.%Main.Float32ToFloat64 [concrete = constants.%Float32ToFloat64]
-// CHECK:STDOUT:   %float.loc6: Core.FloatLiteral = float_value 1 [concrete = constants.%float.a31]
+// CHECK:STDOUT:   %float.loc6: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float.674]
 // 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> = bound_method %float.loc6, %impl.elem0.loc6 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.bcb]
+// CHECK:STDOUT:   %bound_method.loc6_31.1: <bound method> = bound_method %float.loc6, %impl.elem0.loc6 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.6d0]
 // CHECK:STDOUT:   %specific_fn.loc6: <specific function> = 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> = bound_method %float.loc6, %specific_fn.loc6 [concrete = constants.%bound_method.495]
+// CHECK:STDOUT:   %bound_method.loc6_31.2: <bound method> = 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:   %Float32ToFloat64.ref.loc7: %Float32ToFloat64.type = name_ref Float32ToFloat64, imports.%Main.Float32ToFloat64 [concrete = constants.%Float32ToFloat64]
-// CHECK:STDOUT:   %float.loc7: Core.FloatLiteral = float_value 9.9999999999999988E+29 [concrete = constants.%float.f26]
+// 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> = bound_method %float.loc7, %impl.elem0.loc7 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.6ef]
+// CHECK:STDOUT:   %bound_method.loc7_31.1: <bound method> = bound_method %float.loc7, %impl.elem0.loc7 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.a5c]
 // CHECK:STDOUT:   %specific_fn.loc7: <specific function> = 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> = bound_method %float.loc7, %specific_fn.loc7 [concrete = constants.%bound_method.f39]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7: init %f32 = call %bound_method.loc7_31.2(%float.loc7) [concrete = constants.%float.2d0]
-// CHECK:STDOUT:   %.loc7_31.1: %f32 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7 [concrete = constants.%float.2d0]
-// CHECK:STDOUT:   %.loc7_31.2: %f32 = converted %float.loc7, %.loc7_31.1 [concrete = constants.%float.2d0]
+// CHECK:STDOUT:   %bound_method.loc7_31.2: <bound method> = 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:   <elided>
 // CHECK:STDOUT: }
@@ -831,7 +835,7 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // 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:   %float.be6: Core.FloatLiteral = float_value 0 [concrete]
+// CHECK:STDOUT:   %float.1f7: Core.FloatLiteral = float_literal_value 0e-1 [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.6ec: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]
 // CHECK:STDOUT:   %ImplicitAs.Convert.type.726: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%f64.d77) [concrete]
 // CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
@@ -842,9 +846,9 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf = struct_value () [concrete]
 // CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.6ec = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.857) [concrete]
 // CHECK:STDOUT:   %.678: type = fn_type_with_self_type %ImplicitAs.Convert.type.726, %ImplicitAs.facet [concrete]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.be6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.be6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %float.0a8: %f64.d77 = float_value 0 [concrete]
 // CHECK:STDOUT:   %Float64ToFloat64.type: type = fn_type @Float64ToFloat64 [concrete]
 // CHECK:STDOUT:   %Float64ToFloat64: %Float64ToFloat64.type = struct_value () [concrete]
@@ -886,7 +890,7 @@ let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 0 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 0e-1 [concrete = constants.%float.1f7]
 // CHECK:STDOUT:   %Float64ToFloat64.ref: %Float64ToFloat64.type = name_ref Float64ToFloat64, imports.%Main.Float64ToFloat64 [concrete = constants.%Float64ToFloat64]
 // CHECK:STDOUT:   %not_constant_64.ref: %f64.d77 = name_ref not_constant_64, file.%not_constant_64
 // CHECK:STDOUT:   %Float64ToFloat64.call: init %f64.d77 = call %Float64ToFloat64.ref(%not_constant_64.ref)

+ 3 - 22
toolchain/check/testdata/builtins/float/div.carbon

@@ -68,35 +68,16 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
   return BadReturnType(a, b);
 }
 
-// --- literal.carbon
+// --- fail_literal.carbon
 
 library "[[@TEST_NAME]]";
 
 fn Literal() -> type = "float_literal.make_type";
-fn DivLiteral(a: Literal(), b: Literal()) -> Literal() = "float.div";
-
-// --- literal_comptime.carbon
-
-library "[[@TEST_NAME]]";
-import library "literal";
-
-let n: Literal() = DivLiteral(1.0, 2.0);
-
-// --- fail_literal_runtime.carbon
-
-library "[[@TEST_NAME]]";
-import library "literal";
-
-var m: Literal();
-// CHECK:STDERR: fail_literal_runtime.carbon:[[@LINE+8]]:20: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]
-// CHECK:STDERR: let n: Literal() = DivLiteral(1.0, m);
-// CHECK:STDERR:                    ^~~~~~~~~~~~~~~~~~
-// CHECK:STDERR: fail_literal_runtime.carbon:[[@LINE-6]]:1: in import [InImport]
-// CHECK:STDERR: literal.carbon:5:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]
+// CHECK:STDERR: fail_literal.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.div" [InvalidBuiltinSignature]
 // CHECK:STDERR: fn DivLiteral(a: Literal(), b: Literal()) -> Literal() = "float.div";
 // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-let n: Literal() = DivLiteral(1.0, m);
+fn DivLiteral(a: Literal(), b: Literal()) -> Literal() = "float.div";
 
 // CHECK:STDOUT: --- float_div.carbon
 // CHECK:STDOUT:

+ 5 - 30
toolchain/check/testdata/builtins/float/eq.carbon

@@ -38,41 +38,16 @@ library "[[@TEST_NAME]]";
 // CHECK:STDERR:
 fn WrongResult(a: f64, b: f64) -> f64 = "float.eq";
 
-// --- fail_runtime_literal.carbon
+// --- fail_literal.carbon
 
 library "[[@TEST_NAME]]";
 
+// CHECK:STDERR: fail_literal.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.eq" [InvalidBuiltinSignature]
+// CHECK:STDERR: fn Eq(a: Core.FloatLiteral(), b: Core.FloatLiteral()) -> bool = "float.eq";
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
 fn Eq(a: Core.FloatLiteral(), b: Core.FloatLiteral()) -> bool = "float.eq";
 
-fn Test(n: Core.FloatLiteral()) {
-  // OK
-  Eq(1.0, 1.0);
-  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]
-  // CHECK:STDERR:   Eq(n, 1.0);
-  // CHECK:STDERR:   ^~~~~~~~~~
-  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE-8]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]
-  // CHECK:STDERR: fn Eq(a: Core.FloatLiteral(), b: Core.FloatLiteral()) -> bool = "float.eq";
-  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
-  Eq(n, 1.0);
-  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]
-  // CHECK:STDERR:   Eq(1.0, n);
-  // CHECK:STDERR:   ^~~~~~~~~~
-  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE-16]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]
-  // CHECK:STDERR: fn Eq(a: Core.FloatLiteral(), b: Core.FloatLiteral()) -> bool = "float.eq";
-  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
-  Eq(1.0, n);
-  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]
-  // CHECK:STDERR:   Eq(n, n);
-  // CHECK:STDERR:   ^~~~~~~~
-  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE-24]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]
-  // CHECK:STDERR: fn Eq(a: Core.FloatLiteral(), b: Core.FloatLiteral()) -> bool = "float.eq";
-  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
-  Eq(n, n);
-}
-
 // CHECK:STDOUT: --- float_eq.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {

+ 5 - 30
toolchain/check/testdata/builtins/float/less_eq.carbon

@@ -32,41 +32,16 @@ fn RuntimeCallIsValid(a: f64, b: f64) -> bool {
   //@dump-sem-ir-end
 }
 
-// --- fail_runtime_literal.carbon
+// --- fail_literal.carbon
 
 library "[[@TEST_NAME]]";
 
+// CHECK:STDERR: fail_literal.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.less_eq" [InvalidBuiltinSignature]
+// CHECK:STDERR: fn LessEq(a: Core.FloatLiteral(), b: Core.FloatLiteral()) -> bool = "float.less_eq";
+// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
 fn LessEq(a: Core.FloatLiteral(), b: Core.FloatLiteral()) -> bool = "float.less_eq";
 
-fn Test(n: Core.FloatLiteral()) {
-  // OK
-  LessEq(1.0, 1.0);
-  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]
-  // CHECK:STDERR:   LessEq(n, 1.0);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~
-  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE-8]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]
-  // CHECK:STDERR: fn LessEq(a: Core.FloatLiteral(), b: Core.FloatLiteral()) -> bool = "float.less_eq";
-  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
-  LessEq(n, 1.0);
-  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]
-  // CHECK:STDERR:   LessEq(1.0, n);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~
-  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE-16]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]
-  // CHECK:STDERR: fn LessEq(a: Core.FloatLiteral(), b: Core.FloatLiteral()) -> bool = "float.less_eq";
-  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
-  LessEq(1.0, n);
-  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]
-  // CHECK:STDERR:   LessEq(n, n);
-  // CHECK:STDERR:   ^~~~~~~~~~~~
-  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE-24]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]
-  // CHECK:STDERR: fn LessEq(a: Core.FloatLiteral(), b: Core.FloatLiteral()) -> bool = "float.less_eq";
-  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
-  LessEq(n, n);
-}
-
 // CHECK:STDOUT: --- float_less_eq.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {

+ 3 - 22
toolchain/check/testdata/builtins/float/mul.carbon

@@ -66,35 +66,16 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
   return BadReturnType(a, b);
 }
 
-// --- literal.carbon
+// --- fail_literal.carbon
 
 library "[[@TEST_NAME]]";
 
 fn Literal() -> type = "float_literal.make_type";
-fn MulLiteral(a: Literal(), b: Literal()) -> Literal() = "float.mul";
-
-// --- literal_comptime.carbon
-
-library "[[@TEST_NAME]]";
-import library "literal";
-
-let n: Literal() = MulLiteral(1.0, 2.0);
-
-// --- fail_literal_runtime.carbon
-
-library "[[@TEST_NAME]]";
-import library "literal";
-
-var m: Literal();
-// CHECK:STDERR: fail_literal_runtime.carbon:[[@LINE+8]]:20: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]
-// CHECK:STDERR: let n: Literal() = MulLiteral(1.0, m);
-// CHECK:STDERR:                    ^~~~~~~~~~~~~~~~~~
-// CHECK:STDERR: fail_literal_runtime.carbon:[[@LINE-6]]:1: in import [InImport]
-// CHECK:STDERR: literal.carbon:5:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]
+// CHECK:STDERR: fail_literal.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.mul" [InvalidBuiltinSignature]
 // CHECK:STDERR: fn MulLiteral(a: Literal(), b: Literal()) -> Literal() = "float.mul";
 // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-let n: Literal() = MulLiteral(1.0, m);
+fn MulLiteral(a: Literal(), b: Literal()) -> Literal() = "float.mul";
 
 // CHECK:STDOUT: --- mul_sub.carbon
 // CHECK:STDOUT:

+ 3 - 22
toolchain/check/testdata/builtins/float/sub.carbon

@@ -66,35 +66,16 @@ fn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {
   return BadReturnType(a, b);
 }
 
-// --- literal.carbon
+// --- fail_literal.carbon
 
 library "[[@TEST_NAME]]";
 
 fn Literal() -> type = "float_literal.make_type";
-fn SubLiteral(a: Literal(), b: Literal()) -> Literal() = "float.sub";
-
-// --- literal_comptime.carbon
-
-library "[[@TEST_NAME]]";
-import library "literal";
-
-let n: Literal() = SubLiteral(1.0, 2.0);
-
-// --- fail_literal_runtime.carbon
-
-library "[[@TEST_NAME]]";
-import library "literal";
-
-var m: Literal();
-// CHECK:STDERR: fail_literal_runtime.carbon:[[@LINE+8]]:20: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]
-// CHECK:STDERR: let n: Literal() = SubLiteral(1.0, m);
-// CHECK:STDERR:                    ^~~~~~~~~~~~~~~~~~
-// CHECK:STDERR: fail_literal_runtime.carbon:[[@LINE-6]]:1: in import [InImport]
-// CHECK:STDERR: literal.carbon:5:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]
+// CHECK:STDERR: fail_literal.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function "float.sub" [InvalidBuiltinSignature]
 // CHECK:STDERR: fn SubLiteral(a: Literal(), b: Literal()) -> Literal() = "float.sub";
 // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-let n: Literal() = SubLiteral(1.0, m);
+fn SubLiteral(a: Literal(), b: Literal()) -> Literal() = "float.sub";
 
 // CHECK:STDOUT: --- float_sub.carbon
 // CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/builtins/float_literal/make_type.carbon

@@ -32,7 +32,7 @@ var f: FloatLiteral() = 1.0;
 // CHECK:STDOUT:   %FloatLiteral.type: type = fn_type @FloatLiteral [concrete]
 // CHECK:STDOUT:   %FloatLiteral: %FloatLiteral.type = struct_value () [concrete]
 // CHECK:STDOUT:   %pattern_type.dab: type = pattern_type Core.FloatLiteral [concrete]
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -56,7 +56,7 @@ var f: FloatLiteral() = 1.0;
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float]
 // CHECK:STDOUT:   assign file.%f.var, %float
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }

+ 2 - 2
toolchain/check/testdata/function/call/fail_param_type.carbon

@@ -41,7 +41,7 @@ fn F() {
 // CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]
 // CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]
 // CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]
 // CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -86,7 +86,7 @@ fn F() {
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float]
 // CHECK:STDOUT:   %.loc28: %i32 = converted %float, <error> [concrete = <error>]
 // CHECK:STDOUT:   %G.call: init %empty_tuple.type = call %G.ref(<error>)
 // CHECK:STDOUT:   return

+ 4 - 4
toolchain/check/testdata/function/call/fail_return_type_mismatch.carbon

@@ -36,7 +36,7 @@ fn Run() {
 // CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]
 // CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]
 // CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]
-// CHECK:STDOUT:   %float.a31: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %float.674: Core.FloatLiteral = float_literal_value 10e-1 [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]
 // CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.6ec: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]
@@ -50,9 +50,9 @@ fn Run() {
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf = struct_value () [concrete]
 // CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.6ec = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.857) [concrete]
 // CHECK:STDOUT:   %.678: type = fn_type_with_self_type %ImplicitAs.Convert.type.726, %ImplicitAs.facet [concrete]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.a31, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.674, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.a31, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %bound_method: <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:   %Run.type: type = fn_type @Run [concrete]
 // CHECK:STDOUT:   %Run: %Run.type = struct_value () [concrete]
@@ -105,7 +105,7 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Foo() -> %f64.d77 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete = constants.%float.a31]
+// 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.loc15_29.1: <bound method> = bound_method %float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]
 // CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]

+ 2 - 2
toolchain/check/testdata/index/fail_array_non_int_indexing.carbon

@@ -53,7 +53,7 @@ var b: i32 = a[2.6];
 // CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_12.6a3, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_12.1e1: %i32 = int_value 12 [concrete]
 // CHECK:STDOUT:   %array: %array_type = tuple_value (%int_12.1e1) [concrete]
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 2.6000000000000001 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 26e-1 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -117,7 +117,7 @@ var b: i32 = a[2.6];
 // CHECK:STDOUT:   %.loc15_1: init %array_type = converted %.loc15_28.1, %.loc15_28.5 [concrete = constants.%array]
 // CHECK:STDOUT:   assign file.%a.var, %.loc15_1
 // CHECK:STDOUT:   %a.ref: ref %array_type = name_ref a, file.%a [concrete = file.%a.var]
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 2.6000000000000001 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 26e-1 [concrete = constants.%float]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
 // CHECK:STDOUT:   %.loc23_16: %i32 = converted %float, <error> [concrete = <error>]

+ 4 - 4
toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon

@@ -1342,7 +1342,7 @@ fn F() {
 // CHECK:STDOUT:   %ptr.bcc: type = ptr_type %f64.d77 [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.c15: Core.FloatLiteral = float_value 0.80000000000000004 [concrete]
+// CHECK:STDOUT:   %float.c64: Core.FloatLiteral = float_literal_value 8e-1 [concrete]
 // CHECK:STDOUT:   %As.type.6d2: type = facet_type <@As, @As(%f64.d77)> [concrete]
 // CHECK:STDOUT:   %As.Convert.type.8fc: type = fn_type @As.Convert, @As(%f64.d77) [concrete]
 // CHECK:STDOUT:   %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
@@ -1353,9 +1353,9 @@ fn F() {
 // CHECK:STDOUT:   %Core.FloatLiteral.as.As.impl.Convert.6ae: %Core.FloatLiteral.as.As.impl.Convert.type.12c = struct_value () [concrete]
 // CHECK:STDOUT:   %As.facet: %As.type.6d2 = facet_value Core.FloatLiteral, (%As.impl_witness.a23) [concrete]
 // CHECK:STDOUT:   %.d03: type = fn_type_with_self_type %As.Convert.type.8fc, %As.facet [concrete]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.As.impl.Convert.bound: <bound method> = bound_method %float.c15, %Core.FloatLiteral.as.As.impl.Convert.6ae [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.As.impl.Convert.bound: <bound method> = bound_method %float.c64, %Core.FloatLiteral.as.As.impl.Convert.6ae [concrete]
 // CHECK:STDOUT:   %Core.FloatLiteral.as.As.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.As.impl.Convert.6ae, @Core.FloatLiteral.as.As.impl.Convert(%int_64) [concrete]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.c15, %Core.FloatLiteral.as.As.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.c64, %Core.FloatLiteral.as.As.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %float.0fc: %f64.d77 = float_value 0.80000000000000004 [concrete]
 // CHECK:STDOUT:   %Float.as.Destroy.impl.Op.type.cd5: type = fn_type @Float.as.Destroy.impl.Op, @Float.as.Destroy.impl(%int_64) [concrete]
 // CHECK:STDOUT:   %Float.as.Destroy.impl.Op.b8c: %Float.as.Destroy.impl.Op.type.cd5 = struct_value () [concrete]
@@ -1384,7 +1384,7 @@ fn F() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Cpp.ref: <namespace> = 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_value 0.80000000000000004 [concrete = constants.%float.c15]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 8e-1 [concrete = constants.%float.c64]
 // 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:   %impl.elem0: %.d03 = impl_witness_access constants.%As.impl_witness.a23, element0 [concrete = constants.%Core.FloatLiteral.as.As.impl.Convert.6ae]

+ 4 - 4
toolchain/check/testdata/interop/cpp/function/param_unsupported.carbon

@@ -67,7 +67,7 @@ fn F() {
 // CHECK:STDOUT: --- fail_todo_import_unsupported_primitive_type.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1.1000000000000001 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 11e-1 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -81,7 +81,7 @@ fn F() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %foo.ref: <error> = name_ref foo, <error> [concrete = <error>]
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1.1000000000000001 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 11e-1 [concrete = constants.%float]
 // CHECK:STDOUT:   <elided>
 // 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_value 2 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 20e-1 [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
@@ -104,7 +104,7 @@ fn F() {
 // CHECK:STDOUT:   %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %foo.ref: <error> = name_ref foo, <error> [concrete = <error>]
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 2 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 20e-1 [concrete = constants.%float]
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/operators/builtin/fail_type_mismatch_assignment.carbon

@@ -53,7 +53,7 @@ fn Main() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.956, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]
 // CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 5.6000000000000005 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 56e-1 [concrete]
 // CHECK:STDOUT:   %Int.as.Destroy.impl.Op.type.b8f: type = fn_type @Int.as.Destroy.impl.Op, @Int.as.Destroy.impl(%int_32) [concrete]
 // CHECK:STDOUT:   %Int.as.Destroy.impl.Op.715: %Int.as.Destroy.impl.Op.type.b8f = struct_value () [concrete]
 // CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]
@@ -105,7 +105,7 @@ fn Main() {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %a: ref %i32 = bind_name a, %a.var
 // CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 5.6000000000000005 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 56e-1 [concrete = constants.%float]
 // CHECK:STDOUT:   %.loc24: %i32 = converted %float, <error> [concrete = <error>]
 // CHECK:STDOUT:   assign %a.ref, <error>
 // CHECK:STDOUT:   %Int.as.Destroy.impl.Op.bound: <bound method> = bound_method %a.var, constants.%Int.as.Destroy.impl.Op.715

+ 2 - 2
toolchain/check/testdata/operators/builtin/fail_type_mismatch_once.carbon

@@ -33,7 +33,7 @@ fn Main() -> i32 {
 // CHECK:STDOUT:   %Main.type: type = fn_type @Main [concrete]
 // CHECK:STDOUT:   %Main: %Main.type = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 3.4000000000000004 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 34e-1 [concrete]
 // CHECK:STDOUT:   %AddWith.type.e05: type = generic_interface_type @AddWith [concrete]
 // CHECK:STDOUT:   %AddWith.generic: %AddWith.type.e05 = struct_value () [concrete]
 // CHECK:STDOUT:   %int_12: Core.IntLiteral = int_value 12 [concrete]
@@ -70,7 +70,7 @@ fn Main() -> i32 {
 // CHECK:STDOUT: fn @Main() -> %i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc22: %empty_struct_type = struct_literal ()
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 3.4000000000000004 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 34e-1 [concrete = constants.%float]
 // CHECK:STDOUT:   %int_12: Core.IntLiteral = int_value 12 [concrete = constants.%int_12]
 // CHECK:STDOUT:   %impl.elem1: <error> = impl_witness_access <error>, element1 [concrete = <error>]
 // CHECK:STDOUT:   return <error>

+ 2 - 2
toolchain/check/testdata/pointer/fail_address_of_value.carbon

@@ -125,7 +125,7 @@ fn AddressOfParam(param: i32) {
 // CHECK:STDOUT:   %ptr.1d1: type = ptr_type Core.IntLiteral [concrete]
 // CHECK:STDOUT:   %true: bool = bool_literal true [concrete]
 // CHECK:STDOUT:   %ptr.bb2: type = ptr_type bool [concrete]
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete]
 // CHECK:STDOUT:   %ptr.5f5: type = ptr_type Core.FloatLiteral [concrete]
 // CHECK:STDOUT:   %ptr.a45: type = ptr_type String [concrete]
 // CHECK:STDOUT:   %str: String = string_literal "Hello" [concrete]
@@ -235,7 +235,7 @@ fn AddressOfParam(param: i32) {
 // CHECK:STDOUT:   %addr.loc24: %ptr.1d1 = addr_of <error> [concrete = <error>]
 // CHECK:STDOUT:   %true: bool = bool_literal true [concrete = constants.%true]
 // CHECK:STDOUT:   %addr.loc29: %ptr.bb2 = addr_of <error> [concrete = <error>]
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float]
 // CHECK:STDOUT:   %addr.loc34: %ptr.5f5 = addr_of <error> [concrete = <error>]
 // CHECK:STDOUT:   %str: String = string_literal "Hello" [concrete = constants.%str]
 // CHECK:STDOUT:   %addr.loc39: %ptr.a45 = addr_of <error> [concrete = <error>]

+ 4 - 4
toolchain/check/testdata/return/fail_returned_var_type.carbon

@@ -40,7 +40,7 @@ fn Mismatch() -> i32 {
 // CHECK:STDOUT:   %Float.generic: %Float.type = struct_value () [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:   %float.be6: Core.FloatLiteral = float_value 0 [concrete]
+// CHECK:STDOUT:   %float.1f7: Core.FloatLiteral = float_literal_value 0e-1 [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]
 // CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.6ec: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]
@@ -54,9 +54,9 @@ fn Mismatch() -> i32 {
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf = struct_value () [concrete]
 // CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.6ec = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.857) [concrete]
 // CHECK:STDOUT:   %.678: type = fn_type_with_self_type %ImplicitAs.Convert.type.726, %ImplicitAs.facet [concrete]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.be6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.be6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %float.0a8: %f64.d77 = float_value 0 [concrete]
 // CHECK:STDOUT:   %Float.as.Destroy.impl.Op.type.cd5: type = fn_type @Float.as.Destroy.impl.Op, @Float.as.Destroy.impl(%int_64) [concrete]
 // CHECK:STDOUT:   %Float.as.Destroy.impl.Op.b8c: %Float.as.Destroy.impl.Op.type.cd5 = struct_value () [concrete]
@@ -105,7 +105,7 @@ fn Mismatch() -> i32 {
 // CHECK:STDOUT:     %v.var_patt: %pattern_type.0ae = var_pattern %v.patt [concrete]
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %v.var: ref %f64.d77 = var %v.var_patt
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 0 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 0e-1 [concrete = constants.%float.1f7]
 // 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.loc23_12.1: <bound method> = bound_method %float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]
 // CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]

+ 2 - 2
toolchain/check/testdata/return/fail_type_mismatch.carbon

@@ -33,7 +33,7 @@ fn Main() -> i32 {
 // CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
 // CHECK:STDOUT:   %Main.type: type = fn_type @Main [concrete]
 // CHECK:STDOUT:   %Main: %Main.type = struct_value () [concrete]
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]
 // CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]
 // CHECK:STDOUT: }
@@ -68,7 +68,7 @@ fn Main() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Main() -> %i32 {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float]
 // CHECK:STDOUT:   %.loc23: %i32 = converted %float, <error> [concrete = <error>]
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }

+ 2 - 2
toolchain/check/testdata/struct/fail_field_type_mismatch.carbon

@@ -27,7 +27,7 @@ var x: {.a: i32} = {.b = 1.0};
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %i32} [concrete]
 // CHECK:STDOUT:   %pattern_type.268: type = pattern_type %struct_type.a [concrete]
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete]
 // CHECK:STDOUT:   %struct_type.b: type = struct_type {.b: Core.FloatLiteral} [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
@@ -61,7 +61,7 @@ var x: {.a: i32} = {.b = 1.0};
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 1 [concrete = constants.%float]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float]
 // CHECK:STDOUT:   %.loc19: %struct_type.b = struct_literal (%float)
 // CHECK:STDOUT:   assign file.%x.var, <error>
 // CHECK:STDOUT:   return

+ 4 - 4
toolchain/check/testdata/struct/fail_member_access_type.carbon

@@ -28,7 +28,7 @@ var y: i32 = x.b;
 // CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]
 // CHECK:STDOUT:   %struct_type.a.5e8: type = struct_type {.a: %f64.d77} [concrete]
 // CHECK:STDOUT:   %pattern_type.8ce: type = pattern_type %struct_type.a.5e8 [concrete]
-// CHECK:STDOUT:   %float.3ab: Core.FloatLiteral = float_value 4 [concrete]
+// CHECK:STDOUT:   %float.126: Core.FloatLiteral = float_literal_value 40e-1 [concrete]
 // CHECK:STDOUT:   %struct_type.a.b4b: type = struct_type {.a: Core.FloatLiteral} [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]
 // CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]
@@ -42,9 +42,9 @@ var y: i32 = x.b;
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf = struct_value () [concrete]
 // CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.6ec = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.857) [concrete]
 // CHECK:STDOUT:   %.678: type = fn_type_with_self_type %ImplicitAs.Convert.type.726, %ImplicitAs.facet [concrete]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.3ab, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.126, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]
-// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.3ab, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.126, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %float.d15: %f64.d77 = float_value 4 [concrete]
 // CHECK:STDOUT:   %struct: %struct_type.a.5e8 = struct_value (%float.d15) [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
@@ -101,7 +101,7 @@ var y: i32 = x.b;
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 4 [concrete = constants.%float.3ab]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 40e-1 [concrete = constants.%float.126]
 // CHECK:STDOUT:   %.loc15_29.1: %struct_type.a.b4b = struct_literal (%float)
 // 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.loc15_29.1: <bound method> = bound_method %float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]

+ 5 - 5
toolchain/check/testdata/struct/member_access.carbon

@@ -29,7 +29,7 @@ var z: i32 = y;
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %struct_type.a.b.d2f: type = struct_type {.a: %f64.d77, .b: %i32} [concrete]
 // CHECK:STDOUT:   %pattern_type.a7a: type = pattern_type %struct_type.a.b.d2f [concrete]
-// CHECK:STDOUT:   %float.be6: Core.FloatLiteral = float_value 0 [concrete]
+// CHECK:STDOUT:   %float.1f7: Core.FloatLiteral = float_literal_value 0e-1 [concrete]
 // CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]
 // CHECK:STDOUT:   %struct_type.a.b.0cc: type = struct_type {.a: Core.FloatLiteral, .b: Core.IntLiteral} [concrete]
 // CHECK:STDOUT:   %.bc0: ref %f64.d77 = struct_access file.%x.var, element0 [concrete]
@@ -45,9 +45,9 @@ var z: i32 = y;
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.baf = struct_value () [concrete]
 // CHECK:STDOUT:   %ImplicitAs.facet.8d0: %ImplicitAs.type.6ec = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.857) [concrete]
 // CHECK:STDOUT:   %.678: type = fn_type_with_self_type %ImplicitAs.Convert.type.726, %ImplicitAs.facet.8d0 [concrete]
-// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.be6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
+// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03 [concrete]
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]
-// CHECK:STDOUT:   %bound_method.71f: <bound method> = bound_method %float.be6, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
+// CHECK:STDOUT:   %bound_method.728: <bound method> = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %float.0a8: %f64.d77 = float_value 0 [concrete]
 // CHECK:STDOUT:   %.a00: ref %i32 = struct_access file.%x.var, element1 [concrete]
 // CHECK:STDOUT:   %ImplicitAs.type.205: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]
@@ -129,13 +129,13 @@ var z: i32 = y;
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %float: Core.FloatLiteral = float_value 0 [concrete = constants.%float.be6]
+// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 0e-1 [concrete = constants.%float.1f7]
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
 // CHECK:STDOUT:   %.loc15_46.1: %struct_type.a.b.0cc = struct_literal (%float, %int_1)
 // CHECK:STDOUT:   %impl.elem0.loc15_46.1: %.678 = impl_witness_access constants.%ImplicitAs.impl_witness.857, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.a03]
 // CHECK:STDOUT:   %bound_method.loc15_46.1: <bound method> = bound_method %float, %impl.elem0.loc15_46.1 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]
 // CHECK:STDOUT:   %specific_fn.loc15_46.1: <specific function> = specific_function %impl.elem0.loc15_46.1, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc15_46.2: <bound method> = bound_method %float, %specific_fn.loc15_46.1 [concrete = constants.%bound_method.71f]
+// CHECK:STDOUT:   %bound_method.loc15_46.2: <bound method> = bound_method %float, %specific_fn.loc15_46.1 [concrete = constants.%bound_method.728]
 // CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f64.d77 = call %bound_method.loc15_46.2(%float) [concrete = constants.%float.0a8]
 // CHECK:STDOUT:   %.loc15_46.2: init %f64.d77 = converted %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float.0a8]
 // CHECK:STDOUT:   %.loc15_46.3: ref %f64.d77 = struct_access file.%x.var, element0 [concrete = constants.%.bc0]

+ 1 - 2
toolchain/diagnostics/diagnostic_kind.def

@@ -404,8 +404,6 @@ CARBON_DIAGNOSTIC_KIND(DerefOfType)
 CARBON_DIAGNOSTIC_KIND(CompileTimeBindingInVarDecl)
 CARBON_DIAGNOSTIC_KIND(CompoundMemberAccessDoesNotUseBase)
 CARBON_DIAGNOSTIC_KIND(EvalRequiresConstantValue)
-CARBON_DIAGNOSTIC_KIND(RealMantissaTooLargeForI64)
-CARBON_DIAGNOSTIC_KIND(RealExponentTooLargeForI64)
 CARBON_DIAGNOSTIC_KIND(NameDeclDuplicate)
 CARBON_DIAGNOSTIC_KIND(NameDeclPrevious)
 CARBON_DIAGNOSTIC_KIND(NameUseBeforeDecl)
@@ -425,6 +423,7 @@ CARBON_DIAGNOSTIC_KIND(IncompleteTypeInValueConversion)
 CARBON_DIAGNOSTIC_KIND(InCopy)
 CARBON_DIAGNOSTIC_KIND(CharTooLargeForType)
 CARBON_DIAGNOSTIC_KIND(IntTooLargeForType)
+CARBON_DIAGNOSTIC_KIND(FloatTooLargeForType)
 CARBON_DIAGNOSTIC_KIND(IntWidthNotMultipleOf8)
 CARBON_DIAGNOSTIC_KIND(IntWidthNotPositive)
 CARBON_DIAGNOSTIC_KIND(IntWidthTooLarge)

+ 6 - 10
toolchain/lower/constant.cpp

@@ -228,18 +228,14 @@ static auto EmitAsConstant(ConstantContext& context, SemIR::FieldDecl inst)
   return context.GetUnusedConstant(inst.type_id);
 }
 
-static auto EmitAsConstant(ConstantContext& context, SemIR::FloatValue inst)
+static auto EmitAsConstant(ConstantContext& context,
+                           SemIR::FloatLiteralValue /*inst*/)
     -> llvm::Constant* {
-  auto* type = context.GetType(inst.type_id);
-
-  // FloatLiteral is represented as an empty struct. All other floating-point
-  // types are represented as LLVM floating-point types.
-  if (!type->isFloatingPointTy()) {
-    auto* literal_value = context.GetLiteralAsValue();
-    CARBON_CHECK(literal_value->getType() == type);
-    return literal_value;
-  }
+  return context.GetLiteralAsValue();
+}
 
+static auto EmitAsConstant(ConstantContext& context, SemIR::FloatValue inst)
+    -> llvm::Constant* {
   const llvm::APFloat& value = context.sem_ir().floats().Get(inst.float_id);
   return llvm::ConstantFP::get(context.GetType(inst.type_id), value);
 }

+ 2 - 2
toolchain/lower/testdata/array/base.carbon

@@ -22,7 +22,7 @@ fn Run() {
 // CHECK:STDOUT: source_filename = "base.carbon"
 // CHECK:STDOUT:
 // CHECK:STDOUT: @array.237.loc14_3 = internal constant [1 x i32] [i32 1]
-// CHECK:STDOUT: @array.42a.loc15_3 = internal constant [2 x double] [double 0x4026333333333334, double 2.200000e+00]
+// CHECK:STDOUT: @array.b91.loc15_3 = internal constant [2 x double] [double 1.110000e+01, double 2.200000e+00]
 // CHECK:STDOUT: @array.1cb.loc16_3 = internal constant [5 x {}] zeroinitializer
 // CHECK:STDOUT: @tuple.loc17_3 = internal constant { i32, i32, i32 } { i32 1, i32 2, i32 3 }
 // CHECK:STDOUT:
@@ -39,7 +39,7 @@ fn Run() {
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(i64 16, ptr %b.var), !dbg !8
 // CHECK:STDOUT:   %.loc15_37.3.array.index = getelementptr inbounds [2 x double], ptr %b.var, i32 0, i64 0, !dbg !13
 // CHECK:STDOUT:   %.loc15_37.6.array.index = getelementptr inbounds [2 x double], ptr %b.var, i32 0, i64 1, !dbg !13
-// CHECK:STDOUT:   call void @llvm.memcpy.p0.p0.i64(ptr align 8 %b.var, ptr align 8 @array.42a.loc15_3, i64 16, i1 false), !dbg !8
+// CHECK:STDOUT:   call void @llvm.memcpy.p0.p0.i64(ptr align 8 %b.var, ptr align 8 @array.b91.loc15_3, i64 16, i1 false), !dbg !8
 // CHECK:STDOUT:   call void @llvm.lifetime.start.p0(i64 0, ptr %c.var), !dbg !9
 // CHECK:STDOUT:   %.loc16_45.2.array.index = getelementptr inbounds [5 x {}], ptr %c.var, i32 0, i64 0, !dbg !14
 // CHECK:STDOUT:   %.loc16_45.4.array.index = getelementptr inbounds [5 x {}], ptr %c.var, i32 0, i64 1, !dbg !14

+ 20 - 26
toolchain/sem_ir/builtin_function_kind.cpp

@@ -492,24 +492,28 @@ constexpr BuiltinInfo IntGreaterEq = {
     "int.greater_eq", ValidateSignature<auto(IntT, IntU)->Bool>};
 
 // "float.negate": float negation.
-constexpr BuiltinInfo FloatNegate = {"float.negate",
-                                     ValidateSignature<auto(FloatT)->FloatT>};
+constexpr BuiltinInfo FloatNegate = {
+    "float.negate", ValidateSignature<auto(SizedFloatT)->SizedFloatT>};
 
 // "float.add": float addition.
 constexpr BuiltinInfo FloatAdd = {
-    "float.add", ValidateSignature<auto(FloatT, FloatT)->FloatT>};
+    "float.add",
+    ValidateSignature<auto(SizedFloatT, SizedFloatT)->SizedFloatT>};
 
 // "float.sub": float subtraction.
 constexpr BuiltinInfo FloatSub = {
-    "float.sub", ValidateSignature<auto(FloatT, FloatT)->FloatT>};
+    "float.sub",
+    ValidateSignature<auto(SizedFloatT, SizedFloatT)->SizedFloatT>};
 
 // "float.mul": float multiplication.
 constexpr BuiltinInfo FloatMul = {
-    "float.mul", ValidateSignature<auto(FloatT, FloatT)->FloatT>};
+    "float.mul",
+    ValidateSignature<auto(SizedFloatT, SizedFloatT)->SizedFloatT>};
 
 // "float.div": float division.
 constexpr BuiltinInfo FloatDiv = {
-    "float.div", ValidateSignature<auto(FloatT, FloatT)->FloatT>};
+    "float.div",
+    ValidateSignature<auto(SizedFloatT, SizedFloatT)->SizedFloatT>};
 
 // "float.add_assign": float in-place addition.
 constexpr BuiltinInfo FloatAddAssign = {
@@ -537,28 +541,29 @@ constexpr BuiltinInfo FloatConvertChecked = {
     "float.convert_checked", ValidateSignature<auto(FloatT)->FloatU>};
 
 // "float.eq": float equality comparison.
-constexpr BuiltinInfo FloatEq = {"float.eq",
-                                 ValidateSignature<auto(FloatT, FloatT)->Bool>};
+constexpr BuiltinInfo FloatEq = {
+    "float.eq", ValidateSignature<auto(SizedFloatT, SizedFloatT)->Bool>};
 
 // "float.neq": float non-equality comparison.
 constexpr BuiltinInfo FloatNeq = {
-    "float.neq", ValidateSignature<auto(FloatT, FloatT)->Bool>};
+    "float.neq", ValidateSignature<auto(SizedFloatT, SizedFloatT)->Bool>};
 
 // "float.less": float less than comparison.
 constexpr BuiltinInfo FloatLess = {
-    "float.less", ValidateSignature<auto(FloatT, FloatT)->Bool>};
+    "float.less", ValidateSignature<auto(SizedFloatT, SizedFloatT)->Bool>};
 
 // "float.less_eq": float less than or equal comparison.
 constexpr BuiltinInfo FloatLessEq = {
-    "float.less_eq", ValidateSignature<auto(FloatT, FloatT)->Bool>};
+    "float.less_eq", ValidateSignature<auto(SizedFloatT, SizedFloatT)->Bool>};
 
 // "float.greater": float greater than comparison.
 constexpr BuiltinInfo FloatGreater = {
-    "float.greater", ValidateSignature<auto(FloatT, FloatT)->Bool>};
+    "float.greater", ValidateSignature<auto(SizedFloatT, SizedFloatT)->Bool>};
 
 // "float.greater_eq": float greater than or equal comparison.
 constexpr BuiltinInfo FloatGreaterEq = {
-    "float.greater_eq", ValidateSignature<auto(FloatT, FloatT)->Bool>};
+    "float.greater_eq",
+    ValidateSignature<auto(SizedFloatT, SizedFloatT)->Bool>};
 
 // "bool.eq": bool equality comparison.
 constexpr BuiltinInfo BoolEq = {"bool.eq",
@@ -677,19 +682,8 @@ auto BuiltinFunctionKind::IsCompTimeOnly(const File& sem_ir,
     case IntLessEq:
     case IntGreater:
     case IntGreaterEq:
-    case FloatNegate:
-    case FloatAdd:
-    case FloatSub:
-    case FloatMul:
-    case FloatDiv:
-    case FloatEq:
-    case FloatNeq:
-    case FloatLess:
-    case FloatLessEq:
-    case FloatGreater:
-    case FloatGreaterEq:
-      // Integer and floating-point operations are compile-time-only if they
-      // involve literal types. See AnyLiteralTypes comment for explanation.
+      // Integer operations are compile-time-only if they involve literal types.
+      // See AnyLiteralTypes comment for explanation.
       return AnyLiteralTypes(sem_ir, arg_ids, return_type_id);
 
     case TypeAnd:

+ 1 - 0
toolchain/sem_ir/expr_info.cpp

@@ -117,6 +117,7 @@ auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory {
       case FacetType::Kind:
       case FacetValue::Kind:
       case FloatLiteralType::Kind:
+      case FloatLiteralValue::Kind:
       case FloatType::Kind:
       case FloatValue::Kind:
       case FunctionType::Kind:

+ 14 - 4
toolchain/sem_ir/inst_fingerprinter.cpp

@@ -269,10 +269,13 @@ struct Worklist {
   }
 
   auto Add(const llvm::APInt& value) -> void {
-    contents.push_back(value.getBitWidth());
-    for (auto word : llvm::seq((value.getBitWidth() + 63) / 64)) {
+    unsigned width = value.getBitWidth();
+    contents.push_back(width);
+    for (auto word : llvm::seq((width + 63) / 64)) {
       // TODO: Is there a better way to copy the words from an APInt?
-      contents.push_back(value.extractBitsAsZExtValue(64, 64 * word));
+      unsigned start = 64 * word;
+      contents.push_back(
+          value.extractBitsAsZExtValue(std::min(64U, width - start), start));
     }
   }
 
@@ -282,6 +285,13 @@ struct Worklist {
     Add(sem_ir->floats().Get(float_id).bitcastToAPInt());
   }
 
+  auto Add(RealId real_id) -> void {
+    const auto& real = sem_ir->reals().Get(real_id);
+    Add(real.mantissa);
+    Add(real.exponent);
+    contents.push_back(real.is_decimal);
+  }
+
   auto Add(PackageNameId package_id) -> void {
     if (auto ident_id = package_id.AsIdentifierId(); ident_id.has_value()) {
       AddString(sem_ir->identifiers().Get(ident_id));
@@ -325,7 +335,7 @@ struct Worklist {
   }
 
   template <typename T>
-    requires(SameAsOneOf<T, AnyRawId, ExprRegionId, LocId, RealId>)
+    requires(SameAsOneOf<T, AnyRawId, ExprRegionId, LocId>)
   auto Add(T /*arg*/) -> void {
     CARBON_FATAL("Unexpected instruction operand kind {0}", typeid(T).name());
   }

+ 1 - 0
toolchain/sem_ir/inst_kind.def

@@ -66,6 +66,7 @@ CARBON_SEM_IR_INST_KIND(FacetType)
 CARBON_SEM_IR_INST_KIND(FacetValue)
 CARBON_SEM_IR_INST_KIND(FieldDecl)
 CARBON_SEM_IR_INST_KIND(FloatLiteralType)
+CARBON_SEM_IR_INST_KIND(FloatLiteralValue)
 CARBON_SEM_IR_INST_KIND(FloatType)
 CARBON_SEM_IR_INST_KIND(FloatValue)
 CARBON_SEM_IR_INST_KIND(FunctionDecl)

+ 1 - 0
toolchain/sem_ir/inst_namer.cpp

@@ -849,6 +849,7 @@ auto InstNamer::NamingContext::NameInst() -> void {
       AddIntOrFloatTypeName('f', inst.bit_width_id);
       return;
     }
+    case FloatLiteralValue::Kind:
     case FloatValue::Kind: {
       AddInstName("float");
       return;

+ 16 - 1
toolchain/sem_ir/typed_insts.h

@@ -691,7 +691,7 @@ struct FieldDecl {
   ElementIndex index;
 };
 
-// The float literal type. This is currently represented as f64.
+// The float literal type.
 // TODO: Replace this with a rational number type, following the design.
 struct FloatLiteralType {
   static constexpr auto Kind =
@@ -706,6 +706,21 @@ struct FloatLiteralType {
   TypeId type_id;
 };
 
+// A floating point literal value.
+// TODO: Eventually this should be represented as a rational number, and should
+// support arithmetic. For now, we preserve the exact form of the literal
+// produced by the lexer, and don't support any operations, not even unary
+// negation.
+struct FloatLiteralValue {
+  static constexpr auto Kind =
+      InstKind::FloatLiteralValue.Define<Parse::RealLiteralId>(
+          {.ir_name = "float_literal_value",
+           .constant_kind = InstConstantKind::Always});
+
+  TypeId type_id;
+  RealId real_id;
+};
+
 // A floating point type.
 struct FloatType {
   static constexpr auto Kind = InstKind::FloatType.Define<Parse::NoneNodeId>(