Commit Graph
39 Commits
Author SHA1 Message Date
Richard Smith 629f77eb61 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.
2025-08-12 22:08:07 +00:00
Richard Smith 28103b8f2e Convert LegacyFloatType into FloatLiteralType. (#5939)
* Rename the type.
* Change lowering to lower FloatLiteralType values as the placeholder
  `{}` value we use for literals instead of as an LLVM f64.
* Change eval to convert the type as part of a floating point
  conversion, so that lowering can lower converted constants properly.

For now we still represent a value of FloatLiteralType as a
double-precision APFloat. (That will need to change so that we can
losslessly convert literals to f80 / f128 values, and so that we can
convert literals to f32 values without double-rounding.)
2025-08-12 18:55:38 +00:00
694c00c7eb Make Core.Float a class. Add missing builtins for float support. (#5932)
Add missing builtins for float compound assignment, for building a
FloatType, and for converting a float literal to FloatType. Switch
`Core.Float` to being a class and add impls for the various
floating-point operators.

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
2025-08-11 21:01:34 +00:00
37d5046ceb Support parse/check/lower for char (#5901)
toolchain/check/testdata/builtins/char/basics.carbon and
toolchain/lower/testdata/builtins/char.carbon are probably the most
interesting tests here. The parse tests is required because this adds a
new node kind, and we need coverage of it; but the attached info is
minor. There's a fair amount of test churn here because I'm adding the
Core.Char and Core.CharLiteral types as new singletons.

My intent here is that `CharId` is always a unicode code point, even
when the type is a `Char` and thus must be a single UTF-8 code unit
(single byte). This mainly means the stored value of a `CharValue` can
be printed internally without knowing the type.

---------

Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-08-06 20:39:01 +00:00
Richard Smith a508b00883 Fix expected signature for type.and. (#5613)
The former signature unintentionally allowed any parameter and result
types, because it only checked that the type of the type was `type`,
which is tautological (for non-error values). Also add missing tests for
the builtin.
2025-06-04 23:42:20 +00:00
Jon Ross-PerkinsandRichard Smith 949cc21ccc Remove SemIR:: from most sem_ir files (#5358)
This is just cleanup, at least some from LocId replacements.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-04-25 16:06:10 +00:00
Richard Smith b5ae988a08 Add builtins for compound assignment operators. (#5335)
Provide builtins for compound assignments instead of defining them in
the prelude as a use of a binary operator and an assignment. This allows
us to lower compound assignment directly to LLVM operations instead of
producing a function call. In the short term this also allows us to
define a type-generic compound assignment in the prelude.
2025-04-21 20:38:11 +00:00
Dana Jansens c38e723dd8 Rename singleton InstId constants to TypeInstId (#5323)
These constant instructions are all TypeInstId already in their type,
and this makes their names match.

Change the name of MakeSingletonInstId as well and update its comment.
2025-04-17 18:57:20 +00:00
Jon Ross-Perkins 401c72a5c3 Allow no-op functions to have unused arguments (#5318)
For example, we might want `[self: Self]` to be ignored.
2025-04-16 22:03:21 +00:00
Jon Ross-Perkins 4923445e3a Drop Singleton from ErrorInst::SingletonInstId and similar (#5304)
We frequently want to operate on singletons. Per discussion, drop
`Singleton` to make the code shorter.

This started off as wanting to write `inst_id.is_error()`, but the
dependency relationship between ids.h and singleton_insts.h would
require some kind of delayed evaluation to allow the implementation to
remain in headers (which I suspect is helpful to have for inlining). I
could have added something like `IsErrorInst`, forward declared in ids.h
and defined in singleton_insts.h (which would always be included by
typed_insts.h), but the template approach felt like a decent balance
between (a) removing the boilerplate `::SingletonInstId`, (b)
understandability, (c) still visually mirroring if we immediately return
a singleton, and (d) flexibility for more than just `ErrorInst`. But TBH
I'd probably still have written `is_error()` if it didn't require
addressing the cross-header cycle.

Then I tried `SemIR::InstId::Is<SemIR::ErrorInst>`, which generally
worked with types but generated the complaint that it didn't shorten
*all* singleton uses. So pulling back on `::Is`, and instead just
dropping `Singleton`.
2025-04-15 22:40:29 +00:00
Jon Ross-PerkinsandChandler Carruth b49e89e97e Add a no-op builtin function which shouldn't generate code. (#5306)
This is part of a broader plan to have noop destructor functions for
trivial destruction.

Note this emits a SemIR call (`%no_op: init %empty_tuple.type = call
%NoOp.ref() [concrete = constants.%empty_tuple]`), but not LLVM IR. My
thought was this was probably okay, since even though it'll be a little
spammy with destructor calls, the flipside is there'll probably already
be a fair amount for the name reference, and this at least shows when
the call is injected (and discarded).

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2025-04-15 00:33:39 +00:00
Dana Jansens f0663715dd Even more usage of TypeInstId (#5296)
Use TypeInstId in many more places where the instruction is required
to/known to always be a type value. This should be a somewhat exhaustive
set of places, as it covers all instructions given to
GetTypeIdFromTypeInstId().

The things of interest here are:

- Singleton instructions are always of type TypeType, so they are now
TypeInstIds.
- ErrorInst::SingletonInstId gets upcast to be an InstId because it's
sometimes used to define the type of a variable (as in `auto inst_id =
SemIR::ErrorInst::SingletonInstId;` that may hold other InstIds.
- Parse nodes don't really know about TypeInstId, so NodeStack::Push
needs to do some special casing to avoid CHECK failures when given a
TypeInstId but expecting an InstId. We leave a TODO behind here because
the nodes which are being pushed a TypeInstId should probably be taught
to expect that, but such a change is a bit tricky, so too much for this
PR.
2025-04-11 21:47:43 +00:00
Dana Jansens c34a8d0a3a Convert remaining type-value InstId fields to TypeInstId (#5294)
After #5280 there are a few more typed instructions that have an `InstId
type_inst_id` that always holds a type value. These are converted to
`TypeInstId` to encode this fact in the type system. The
`ConvertAggregateElement()` function in convert.cpp is now able to
receive `TypeInstId` for a couple arguments as well.

Additionally, the `type_inst_id` field of `StructTypeField` is made into
a `TypeInstId`.

The `TupleType::elements_id` is renamed to `TupleType::type_elements_id`
to try record the fact that it's an InstBlock of type value
instructions. We don't introduce a TypeInstBlockId at this time, but it
might be nice to make blocks of TypeInstIds in the future.

To assist in working with a block of InstId that are type values, two
additional helpers are added to the TypeStore:
- GetBlockAsTypeInstIds which turns an `ArrayRef<InstId>` into a range
of `TypeInstId`
- GetBlockAsTypeIds which turns an `ArrayRef<InstId>` into a range of
`TypeId`

We use these helpers in places that iterate over the
`TupleType::type_elements_id`.
2025-04-11 20:11:03 +00:00
Richard Smith a74ca9071b Remove all remaining uses of TypeIds as instruction operands. (#5280)
In preparation for shifting from `TypeId`s potentially representing
attached types to always representing unattached types, using
[terminology suggested on
Discord](https://discord.com/channels/655572317891461132/963846118964350976/1359286326779973712).
This change causes us to track slightly more type spelling information
through SemIR.

One change that has significant impact on the SemIR output is that we
now build a `struct_type` instruction in each class representing the
types of the fields, including the spelling used for those types. This
is now no longer always identical to the corresponding canonical
`struct_type` for the object representation, so it's built separately
and owned by the class.

Also remove `TypeBlock` support entirely, as its only use was
representing `TupleType`s, which now use an `InstBlock`.
2025-04-10 20:53:42 +00:00
Dana JansensandJon Ross-Perkins 129cf35d78 Support BitAnd operator between facet types (#5022)
Doing so results in TODOs in the resulting semir, since we don't handle
combining the facet types together properly or doing lookup into them.
There's a test added demonstrating this, which will be made to work in
followups.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-02-27 17:53:48 +00:00
Jon Ross-Perkins 6b5eb1a101 Id::Invalid -> Id::None (#4834)
High level, replacing `Id::Invalid` with `Id::None` and `Id::is_valid`
with `Id::has_value` for clarity, as discussed
[here](https://discord.com/channels/655572317891461132/655578254970716160/1331664574545395794).
The `IntId` refactoring is needed together with `AnyIdBase` because it's
also used with `ValueStore`.

Note, trying to be careful not to rewrite `EnumBase::InvalidIndex`, or
`is_valid` in general (e.g., `IdKind::is_valid`).

I've tried to sequence commits here:

1. Automatic replacements:

- `((?:Id|Index)(?: |::|\(|Base(?:\(|::)))Invalid((?:Index)?\W)` ->
`$1None$2`
  - `<invalid>` -> `<none>`
  - `InvalidNodeId` -> `NoneNodeId`
  - `/\*invalid\*/` -> `/*none*/`
  - `id((?:_|\(\))(?:\.|->))is_valid` -> `id$1has_value`

2. Manual edits:

  - In `int.h` and `int_test.cpp`
    - `IntT` has `is_value`, which I'm renaming to `is_embedded_value`.
    - Manual edits to comments in this file.
  - `AnyIdBase` and `IdBase`
- Declaration of `is_valid` -> `has_value`, `InvalidIndex` ->
`NoneIndex`.
  - In `ids.h` and `ids.cpp`
    - `is_valid` -> `has_value`
- `// An explicitly invalid ID.` -> `// An ID with no value.`; similar
for index
    - Various math on `InvalidIndex` -> `NoneIndex`
    - Various mentions of "valid" in comments
  - In `value_store.h`, for `IdT::Invalid`, plus one comment
- In `impl.h` and `tokenized_buffer.h`, we had different initialization
of `::None` values (versus `ids.h` syntax) that I fixed manually.
  - Spot checks to compile
- Particularly where `is_valid` replacements didn't catch spots due to
different naming.

3. Autoupdate tests

4. verbose.carbon (NOAUTOUPDATE)

5. Comment spot checks

Note there are probably other mentions of "Invalid" that should be swept
up, but I'd like to argue for merging and separating out remaining
cleanup since this is so sweeping (and likely to hit merge conflicts
from churn). We'll probably have lingering mentions of "invalid" for a
bit regardless, just because there are uses of "invalid" in non-Id APIs.
2025-01-22 23:15:00 +00:00
Richard Smith 246ec785df Add support for converting between integer types (#4753)
Add a builtin `"int.convert"` supporting unchecked conversions between
different integer types. This performs a truncation, zero-extension, or
sign-extension, depending on the widths of the operands and the
signedness of the source type. Add explicit `As` support to the prelude.
No implicit conversions are supported yet as we don't have a way to
express the constraint that we can only implicitly convert to wider
types.
2025-01-08 08:25:20 +00:00
Richard Smith 4a7aefefaa Add support for operators on Core.IntLiteral. (#4716)
Fixes integer builtins to produce the correct values (and not
CHECK-fail) when used on integer literals. Also adds impls to the
prelude to use the new builtins to perform operations on integer
literals.

Perhaps most importantly, this allows directly initializing `i32` values
with negative numbers, as the negation operation on integer literals now
works.

For testing I've added tests for use of literals with one operator in
each class (addition, multiplication, ordering, bitwise, etc) for which
there are distinct rules or overflow behavior, rather than exhaustively
testing all the combinations. This is aimed at finding a good tradeoff
between maintainability of the tests and thorough test coverage.

Also fixes lowering of heterogeneous shifts and comparisons. These are
currently disabled when one of the operands is an integer literal, but
we may want to allow that when the integer literal operand has a known
constant value.
2024-12-31 06:36:43 +00:00
Richard Smith c1590f886a Add equality comparison support for bool. (#4701) 2024-12-18 00:47:03 +00:00
Richard Smith 3645143e27 Add solutions for advent of code 2024 day 1 to examples/. (#4673)
In order to support these examples, this adds two new builtins to the
toolchain: `print.char` and `read.char`, which map to the libc functions
`putchar` and `getchar`.
2024-12-17 00:47:51 +00:00
Richard Smith cd1ecf1297 When a builtin function expects type T also allow an adapter for T. (#4643)
Extends the set of function signatures that support being given a
builtin definition to include cases where a parameter or return type is
an adapter for a supported type. For example, if we can give a builtin
definition to `Add(a: i32, b: i32) -> i32`, then we can also give a
builtin definition to `Add(a: MyI32, b: MyI32) - >MyI32` where `MyI32`
adapts `i32`.

This is a prerequisite for changing `Core.Int` to be a class type that
adapts the builtin int type.
2024-12-06 03:13:05 +00:00
Jon Ross-Perkins efab39cbd9 Remove InstId::Builtin members (#4632)
- `InstId::Builtin<Inst>` -> `<Inst>::SingletonInstId`
- `InstId::PackageNamespace` -> `Namespace::PackageInstId`
2024-12-05 18:13:46 +00:00
Jon Ross-Perkins 4a80d6758d Rename the builtin FloatType to LegacyFloatType, Error to ErrorInst (#4555)
This is for more clearly distinct names, and to make it a clearer
transition from `BuiltinInst` for name conflicts. `FloatType` is also an
instruction, and we have `Carbon::Error` (common/error.h). This avoids
affecting tests, although the name is embedded in the builtin test.

In `LegacyFloatType`, `Legacy` because I was having trouble coming up
with a more appropriate name. I'm not clear this is a `FloatLiteralType`
at present, it needs some work to mirror `IntLiteralType`.

In `ErrorInst`, the suffix `Inst` was discussed as good and similar to
`BuiltinInst` (although I'm trying to get rid of that).
2024-11-19 20:37:39 +00:00
Richard SmithandJon Ross-Perkins e2ae5f212c Remove the special case for i32. (#4543)
For the few remaining uses of the builtin `i32` type, manually build an
`IntType(Signed, 32)` value instead. These are:

- The return type of `Run`.
- The type that int literals in an `if` expression are converted into.
- The type of an array index expression.

We should consider converting those three cases away from `i32` over
time.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-11-18 23:19:36 +00:00
Jon Ross-Perkins 4eb955bf42 Drop std:: on size_t in various spots. (#4546)
We predominantly omit the `std::` in these cases already. This is for
style: "Prefer to omit the std:: prefix for these types, as the extra 5
characters do not merit the added clutter."
(https://google.github.io/styleguide/cppguide.html#Integer_Types)
2024-11-18 22:28:57 +00:00
Richard Smith cbd88e5c72 Add builtin for performing checked conversion between integer types. (#4523)
As a prerequisite for switching the type of int literals to be the
`IntLiteral` type, add support for performing conversions of in-bounds
integer constant values to other integer types in which they fit.

This incidentally is our first compile-time-only builtin function, so
add very minimal support for compile-time-only functions while we're
here.
2024-11-14 00:27:40 +00:00
Richard Smith 44fe65fbe5 Rename BigInt to IntLiteral. (#4476)
In preparation for changing the type of integer literals to
`IntLiteral`.
2024-11-02 02:09:10 +00:00
Richard Smith df68bf9f71 Switch to using Core.BigInt as the type of the size of a type literal. (#4450)
This removes one of the few ways in which `i32` is special and gets us
closer to removing it as a special case.
2024-10-28 23:35:08 +00:00
Richard Smith a02dfe0226 Superficial support for Core.BigInt type (#4414)
Add a `Core.BigInt` type and a corresponding builtin type in the
toolchain. See [corresponding section of the
design](https://docs.carbon-lang.dev/docs/design/expressions/literals.html#defined-types).

So far this type is not used for anything, and there is no way to create
an instance of it.
2024-10-16 23:27:01 +00:00
Jon Ross-Perkins 8bb80d8271 Add a basic Core.Print function for ints. (#4078)
We'd been discussing that explorer remains necessary for print, and I
was wondering if this kind of approach would be okay (we _probably_ want
this to work, based on #2110, albeit with more overloads -- but I don't
think there's a good way to support overloads at the moment).

```
╚╡../bazel-bin/examples/sieve
2
3
5
7
11
13
17
19
23
29
31
37
41
43
...
```
2024-06-25 21:32:07 +00:00
Jon Ross-PerkinsandRichard Smith 76ed3c73cb Promote FunctionType to a standard instruction. (#3931)
This removes the builtin FunctionType, replacing it with a FunctionType
instruction. The constant for a FunctionDecl is now a StructValue with
type of FunctionType.

Note this means a function declaration produces _both_ a type, and a
value of the type. This has some consequences in terms of circularity,
and makes the importing of function declarations a little more complex.

It'll get particularly peculiar for imports because of the behavior of
the reference, but that's a known issue due to other things such as
`alias`. The impact will hopefully be contained to
ResolvePrevInstForMerge (and ImportRefs).

To note a small formatting change in diagnostics:

```
-  // CHECK:STDERR: fail_member_lookup.carbon:[[@LINE+4]]:3: ERROR: Value of type `<associated <function> in Interface>` is not callable.
+  // CHECK:STDERR: fail_member_lookup.carbon:[[@LINE+4]]:3: ERROR: Value of type `<associated F in Interface>` is not callable.

-  // CHECK:STDERR: fail_todo_facet_lookup.carbon:[[@LINE+4]]:3: ERROR: Value of type `<associated <function> in Interface>` is not callable.
+  // CHECK:STDERR: fail_todo_facet_lookup.carbon:[[@LINE+4]]:3: ERROR: Value of type `<associated F in Interface>` is not callable.
```

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2024-05-03 15:18:04 +00:00
Pablo Paglilla d28c63df01 Add support for builtin float comparison operations (#3899)
Adds support for builtin comparison operations for floats (`==`, `!=`,
`<`, `<=`, `>`, `>=`).
2024-04-19 23:50:31 +00:00
Pablo Paglilla cae62765af Add builtins for basic float operations (#3897)
Adds support for unary `-` and binary `+`, `-`, `*`, `/` for floating
point types.

Real literals are now transformed to `llvm::APFloat`s during the check
phase into the `FloatLiteral` instruction.

This PR likely collides a bit with #3892 and might need to be updated
when that one is merged.
2024-04-19 22:50:54 +00:00
Richard Smith 5964795f34 Use separate builtins for signed / unsigned arithmetic. (#3892)
Per offline discussion with chandlerc and jonmeow, use different
builtins for signed versus unsigned integer ops instead of looking at
the type. In this commit, the arithmetic builtins (add, sub, negate,
mul, div, mod) are split. I'll apply the same change to comparisons and
to right shift in separate PRs.
2024-04-19 01:42:35 +00:00
bb117aea3a Add support for iN and uN for all suitable N. (#3868)
`i32` is retained as a special case for now, for bootstrapping purposes,
and maps to `BuiltinIntType`, which is distinct from `Core.Int(32)`.
This will be removed later once we support `Core.BigInt`.

For now this provides both the `iN` types and also the builtins to
support `Core.Int(N)`. The intent is that we'll change the `iN` support
to rewrite to calls here when we do that for the other type literals and
type keywords.

No conversions between integer types are supported yet, and all literals
are of type `i32`, so we can't actually form values of any of these new
types.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
2024-04-08 10:09:02 +00:00
Jon Ross-Perkins 6889aff49a Add functions for instantiating builtin types through lookup. (#3857)
Note, my instinct is that `Float(dyn_size)` should be invalid. However,
I think the constant evaluation doesn't result in the call being
evaluated in eval.cpp when the size is non-constant. I think I could get
an error for symbolic phase calls, but that seems a little less
interesting already. Long-term maybe we want a way to mark functions as
_must_ be evaluated during constant phase?

Also, I think there may be a bug with literal value parse node
locations, I should be able to point at the position of `arg_ids[0]` but
it's missing a line number so I point at `loc` instead.
2024-04-04 23:47:06 +00:00
Richard Smith 762d07fa3e Add builtins for integer bitwise, bit-shift, and relational comparison operators. (#3853) 2024-04-03 22:21:55 +00:00
Richard SmithandJon Ross-Perkins ebbc648342 Add builtins for some basic integer operations. (#3816)
Supports unary `-`, and binary `+`, `-`, `*`, `/`, `%`, `==`, `!=`.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-03-27 00:15:52 +00:00
a3d77d9b74 Factor out some parts of builtin handling and add declaration checking. (#3815)
In preparation for adding more builtins, factor out the handling of
builtin function kinds into separate files.

Add checking for builtin function signatures. The mechanism used here is
intended to provide a lot of flexibility for declaring generic builtin
functions and pretty arbitrary constraints on the types of parameters of
builtin functions. For now, these constraints are checked when the
builtin function is declared. The hope is that this will suffice, but if
not, it should be straightforward to switch to doing some of the
checking on call and share logic between the checks.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
2024-03-26 22:58:11 +00:00