Issue was not properly handling `ImportRef` instructions in
`AddAssociatedEntities` in `check/import_ref.cpp`. Using `CARBON_CHECK`
instead of `CARBON_FATAL` was hiding the error.
---------
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
`ids.h` and `ids.cpp` are the manual edits, everything else is
search-and-replace.
The full list of things moved is:
- `TypeId::TypeType`
- `TypeId::AutoType`
- `TypeId::Error`
- `ConstantId::Error`
This is to unblock removing `InstId::Builtin*`.
* Rewrite constraints are stored in a facet type, substituted, imported,
and formatted.
* We now distinguish `.Self` from other symbolic bindings in two ways:
* `.Self` itself now has an invalid compile time binding index (since it
doesn't bind to any of the generic parameters). As a result, we no
longer need to create a generic region in `handle_where.cpp`.
* There is a new phase tracking values that are only symbolic because
they transitively depend on `.Self`. This allows us to give the result
of a `where` expression template phase as long as it doesn't use any
symbolic constants other than `.Self` or other designators.
* `AddConstant` has been removed from `check/context` since it was only
used from `eval`. This meant less plumbing of the phase change.
* Evaluation of `BindSymbolicName` now also performs substitution into
its type.
* Include a bit more information in some diagnostics.
* `StringifyTypeExpr` outputs rewrites, which required adding support
for associated entities as well.
* Associated entities now have an entity name set when importing.
* Adds tests for some interesting cases with rewrites and uses of
`.Self` mixed with other symbolic constants.
Still to do:
* There is no validation that any particular type satisfies rewrite
constraints.
* Access to members of a facet type do not see the rewritten values.
* Impls don't recognize whether associated constants have rewrites
setting their values.
* No support for resolving facet types.
---------
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Goal is to reduce churn in names in test updates (by churning a lot of
them in this PR).
---------
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
The Any[...] instruction group structs have a field layout that matches
the specific typed instructions that it groups together. However those
specific instructions may have different field types, or different
numbers of fields, making it impossible for the Any[...] instruction
group to match them all at once.
In this case, it can use the AnyRawId field type to represent that the
specific typed instructions have different field types in that position,
or may not have a field at all.
Previously we used `int32_t` as this polymorphic placeholder type, which
was implicit and worked somewhat magically:
- It was not listed in IdKind
- It was was not implemented explicitly for either FromRaw or ToRaw
However it happened to work because:
- FromRaw<T> was implemented for every T, and would build as long as T
was constructible from the raw id value, which is int32_t.
- In As<AnyGroupInstruction> for converting a specific instruction to a
group instruction: For any given id field type T in the specific type
struct, it would be converted to its raw (int32_t) value, then the
AnyGroupInstruction field would be constructed with FromRaw<int32_t>
since the polymorphic field type was int32_t.
- Of course int32_t is constructible from int32_t.
- And if the specific instruction did not have a field in the matching
position, the AnyGroupInstruction's field would be default
constructed, and int32_t is default constructible.
This allowed As<AnyGroupInstruction> to construct the
AnyGroupInstruction type
from each of its specific instruction types regardless of what field
types they had.
We can make this more explicit by using a type other than int32_t. We
introduce the AnyRawId specifically for the purpose of being a
polymorphic field type in Any[...] instruction groups.
The AnyRawId type _is_ part of IdKind, removing the need for a special
case in the documentation and rules about field types. And this allows
us to `require` that T is in IdKind for FromRaw<T>.
- This also pointed out that FromRaw and ToRaw do not need to be
implemented for BuiltinTypeKind anymore, as this is no longer a field
type in any typed instructions, further simplifying the rules to not
need any exceptions for what is a valid field type.
The AnyRawId type participates in FromRaw by being a member of IdKind
and being constructible from int32_t.
The AnyRawId type is default constuctible so that when the specific
typed instruction has no field in the matching position, it will be
default-constructed with the InstId::InvalidIndex value.
The AnyRawId type does _not_ participate in ToRaw, and this is
documented on the type. This is because conversion from specific typed
instruction to an instruction group is lossy (due to the polymorphism
which requires the AnyRawId type). As such conversion from the
instruction group to a specific instruction is not possible, and thus
the Any[...] instruction group does not need to support being converted
to raw id values.
This is rebased on #4604.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
In llvm 17 the _LIBCPP_ENABLE_ASSERTIONS flag was split into two:
- _LIBCPP_ENABLE_HARDENED_MODE for fast checks
- _LIBCPP_ENABLE_DEBUG_MODE for expensive checks
We kept HARDENED_MODE enabled in debug, but we can also turn it on for
opt builds.
In llvm 18, the _LIBCPP_ENABLE_HARDENED_MODE was further split into 4
settings, NONE, FAST, EXTENSIVE, DEBUG. As seen in the recent blog post
https://security.googleblog.com/2024/11/retrofitting-spatial-safety-to-hundreds.html
the FAST hardening mode is indeed very fast and has minimal impact,
while helping to catch a lot of bugs.
So we enable the FAST checks in opt builds, and EXTENSIVE checks in
debug builds.
The EXTENSIVE checks are the same that Chrome enables in every build
configuration, so we could consider enabling it in opt builds as well:
https://source.chromium.org/chromium/chromium/src/+/main:build/config/compiler/BUILD.gn;l=1127;drc=a8260dee097dde71ca4464c0c8d897a80c353db2
Adds a singleton framework, and converts `File` and `InstId::Print` to
demonstrate functionality. Moves various functions from `ids.h` to
`ids.cpp` because `Inst::Print` needs the file if `singleton_insts.h` is
split out, so the small bit of cleanup feels consistent.
I added `Inst::MakeSingleton` because getting the type of the
instruction to make from an `InstKind` felt too hard. Singleton
instructions follow a basic structure, so I'm just putting that
instruction structure into `Inst`. Previously we required macros to do
this, and I'm trying to remove macro dependencies.
I'm trying to remove builtin/singleton-related functionality from
`InstId` in order to get a clearer boundary for the functionality. The
other builtin functions should be removed as part of the bigger
migration, but I'm trying to carefully scope changes to verify agreement
on the singleton approach in use first.
This provides `InstT::SingletonInstId` because that'll often be written
as `SemIR::TypeType::SingletonInstId`. The alternative of something like
`SemIR::SingletonInstId<SemIR::TypeType>` is just a little more verbose
due to the repeated `SemIR`, and it's more consistent with
`TypeType::Kind`.
An alternative I considered was consolidating singleton information to
`InstKind`. This felt challenging because of the
`InstId::BuiltinTypeType` and similar values. Maintaining those would
turn into something like `InstKind::IsSingleton()` and
`InstId::Singleton<TypeType>`, which didn't feel like as good a split.
`InstId::Print` remains aware of singletons, but I'm hoping to remove
other builtin-related calls from `InstId`.
Another thing I considered was adding `.is_singleton = true` to
`InstKind::Definition`. I don't think we could rely on that to get
`InstId::Singleton<TypeType>` set up as `constexpr`, though. At that
point, I think it'd mainly be _just_ a comment-like annotation, maybe
validated with `CHECK` but not having any effect on its own. So I
decided not to do that, just adding comments instead.
Sidenotes:
- "singleton" naming was discussed [on
#toolchain](https://discord.com/channels/655572317891461132/655578254970716160/1308870233729269781).
- The TODO in file.h about possibly excluding other things than
singletons seems moot. That's for raw IR, and we're much more focused on
textual IR these days.
---------
Co-authored-by: David Blaikie <dblaikie@gmail.com>
Co-authored-by: Dana Jansens <danakj@orodu.net>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
Co-authored-by: Boaz Brickner <brickner@google.com>
Co-authored-by: Geoff Romer <gromer@google.com>
The documentation still referred to typed instructions having a
Parse::Node field, however that was removed and moved to the InstStore
in f197219c10.
Then GetParseNode() was renamed to GetNodeId() in 86a7c9ff45 and
then GetLocationId() in b079acd86f and finally GetLocId() in
b5d28f2c4b.
The comment in typed_inst.h mentions only three fields now, but some
types still have four, thanks to the unmentioned `ElementIndex index`
field. Normally this field comes last, after the `[...]Id` fields except
for in one case, AssociatedEntity. Rather than write ambiguously ordered
documentation, update the comment to and docs to say that the
ElementIndex comes last, and move it to the last position in
AssociatedEntity. Tests are rebased accordingly.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
The current representation has two nested presence indicatators (the
optional bool, the null pointer). Currently the pointer is never null,
but the style guide suggests that T* should be used for parameters that
may or may not be present, so we do not need the optional here.
> When passing an object's address as an argument, use a reference
> unless one of the following cases applies:
>
> - If the parameter is optional, use a pointer and document that it
> may be null.
Once the parameter is just a pointer, the ScopedTiming field does not
need an optional either, and can just store the pointer.
It would be more preferable to have an optional representation of a
sometimes-null pointer like optional<T&> to describe a sometimes-null
pointer, as this would allow clearer runtime diagnostics when used
incorrectly (a check failure in unwrapping) and would be better
self-documenting through syntax instead of a comment. But we do not
currently have such a primitive.
Use it in the remaining few places where we currently hardcode `i32`: as
the index type in array indexing, as the type for literals in `if`
expressions, and as a valid return type for `Run`.
In preparation for changing `Core.Int` to be a class.
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
The only documentation I can find for `.bazelversion` is in
https://github.com/bazelbuild/bazelisk/blob/master/README.md. However,
`bazel` will error out if it doesn't match the `.bazelversion`. For
example:
```
╚╡/usr/bin/bazel build :all
ERROR: The project you're trying to build requires Bazel 7.3.0 (specified in [elided]/carbon-lang/.bazelversion), but it wasn't found in /usr/bin.
```
Switching to this because the `MODULE.bazel` requires tighter version
pinning in order to avoid churn, and this should help catch mistakes
early.
In `MODULE.bazel`, demote mention of the version issue because it should
only really occur now when the version is being deliberately changed, so
the connection should be more apparent.
If they were called twice for a CompilationUnit, they would destroy
objects that they created and returned a pointer to, leaving a dangling
pointer somewhere else.
The Inst type will type erase a specific typed instruction by storing
the kind as an integer. It does this by calling InstKind::AsInt on a
runtime or compile-time InstKind. Then it returns the kind as InstKind
by reconstituting it from the integer.
Currently it does a cast to a raw enumerator and then calls
InstKind::Make. However Make is designed to be more of an internal
detail. The more clearly paired inverse operation is InstKind::FromInt,
which is documented as being intended to be exposed by derived classes
like InstKind.
This seems slightly redundant for a locally-defined class, where there
will be a complete_type_witness instruction earlier in the class, but is
important for imported classes, where we're currently doing the wrong
thing in a way that's invisible in formatted SemIR.
Represent the type as an `InstId` rather than as a `TypeId` to preserve
how it was written and better support tracking its value in a generic.
Add accessors to `Class` to get the base and adapted type to reduce code
duplication, and add `TypeStore::GetObjectRepr` to make it easier to map
from a type to its possibly-adapted object representation type. In
passing, also move `GetIntTypeInfo` and `GetUnqualifiedType` into
`TypeStore`.
This fixes specifics of generic adapters to properly look at the
specific adapted type, and also fixes importing of adapters.
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
* Make the step stack into a class
* Make the operations on the stack (pushing, popping, test for done)
into methods on the stack class.
* Add more kinds of steps (array bound and name).
* Rewrite cases to use the new kinds of steps. Afterward, none use
`Step::Next()` or the step index, so those get removed.
* Add another convenience method `PushTypeId`.
* Remove the `SemIR::File&` member from the steps, since it doesn't
change.
Hopefully using `step_stack.Push`... calls makes it clear that they are
resolved in the reverse order they are executed.
---------
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
This changes to an `Error` return to let the driver do the "error: "
prefix, except for one case with `help` that needs more work to change
(I'm not planning on picking up that TODO). It also changes
capitalization, backtick use, and a few minor punctuation things to try
to better match the diagnostic style.
This also adds `Error` matchers so that the changes to command line
testing are clearer.
We considered a couple of other options for this:
* https://github.com/carbon-language/carbon-lang/pull/4515 Keep the
`ElementIndex` numbering vptr-ignorant, and do +1 offsets as needed -
seems subtle/easy to miss
* https://github.com/carbon-language/carbon-lang/pull/4517 Always have a
zeroth element in the object representation, make it zero-size in the
case of no-vptr - @zygoloid was concerned this would add overhead
especially to stateless objects used in type-trait-like things.
But currently moving forward with this direction - of initializing field
indexes with an invalid value until the end of the class definition,
then assigning field indexes during construction of the class's object
representation struct type. This direction might reinforce/help avoid
premature access to the object representation before the class is
complete, and give a single place where class layout is done (at class
completion) if we want to add more options there, such as class layout
optimizations, etc.
This patch still has problems with object initialization (that #4515
does not have/does address) but does address normal `obj.member` access
correctly.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
The switch defaults to true, so it's displayed as `--no-debug-info` in
the help. The description should be agnostic about whether the flag will
enable or disable the behaviour.
I had removed most but not all of the hashtable prefetching during
development because I wasn't confident in the benchmarking results.
However, I never revisited this once the benchmarking infrastructure
improved and there were solid and stable results.
This factors the two interesting prefetch patterns I've seen for this
style of hashtable into helpers that are always called, and provides
macros that can be used during the build to configure exactly which
prefetch strategies are enabled.
Benchmarking these and gaining confidence is very frustrating -- even
now with the improved infrastructure, the noise is much higher than I
would like. But it seems clear that *some* prefetching is a significant
win. It also seems like enabling both results in too much prefetch
traffic. And the entry group prefetch appears to be significantly more
effective, both for the most interesting of the microbenchmarks and
maybe most importantly for our compilation benchmarks. There, AMD is
helped substantially and M1 seems to be helped some (although harder to
measure).
AMD server benchmark numbers:
```
name old cpu/op new cpu/op delta
BM_CompileAPIFileDenseDecls<Phase::Lex>/256 35.0µs ± 2% 34.2µs ± 2% -2.40% (p=0.000 n=20+19)
BM_CompileAPIFileDenseDecls<Phase::Lex>/1024 156µs ± 2% 151µs ± 2% -3.18% (p=0.000 n=20+19)
BM_CompileAPIFileDenseDecls<Phase::Lex>/4096 625µs ± 1% 605µs ± 1% -3.22% (p=0.000 n=19+18)
BM_CompileAPIFileDenseDecls<Phase::Lex>/16384 2.79ms ± 1% 2.69ms ± 2% -3.67% (p=0.000 n=17+19)
BM_CompileAPIFileDenseDecls<Phase::Lex>/65536 12.1ms ± 1% 11.6ms ± 1% -4.30% (p=0.000 n=17+18)
BM_CompileAPIFileDenseDecls<Phase::Lex>/262144 56.6ms ± 1% 53.8ms ± 1% -5.00% (p=0.000 n=18+17)
BM_CompileAPIFileDenseDecls<Phase::Parse>/256 61.1µs ± 2% 61.7µs ± 1% +0.87% (p=0.000 n=19+19)
BM_CompileAPIFileDenseDecls<Phase::Parse>/1024 288µs ± 1% 290µs ± 1% +0.55% (p=0.004 n=20+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/4096 1.16ms ± 1% 1.16ms ± 1% -0.54% (p=0.000 n=17+19)
BM_CompileAPIFileDenseDecls<Phase::Parse>/16384 4.98ms ± 1% 4.91ms ± 1% -1.39% (p=0.000 n=20+19)
BM_CompileAPIFileDenseDecls<Phase::Parse>/65536 20.9ms ± 1% 20.5ms ± 1% -1.86% (p=0.000 n=20+19)
BM_CompileAPIFileDenseDecls<Phase::Parse>/262144 92.1ms ± 1% 90.2ms ± 1% -2.12% (p=0.000 n=18+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/256 1.16ms ± 2% 1.16ms ± 1% ~ (p=0.931 n=19+19)
BM_CompileAPIFileDenseDecls<Phase::Check>/1024 2.17ms ± 2% 2.16ms ± 1% ~ (p=0.247 n=20+19)
BM_CompileAPIFileDenseDecls<Phase::Check>/4096 6.07ms ± 1% 6.04ms ± 1% -0.48% (p=0.007 n=19+19)
BM_CompileAPIFileDenseDecls<Phase::Check>/16384 22.4ms ± 1% 22.2ms ± 1% -0.99% (p=0.000 n=20+19)
BM_CompileAPIFileDenseDecls<Phase::Check>/65536 93.3ms ± 1% 92.2ms ± 1% -1.23% (p=0.000 n=20+18)
BM_CompileAPIFileDenseDecls<Phase::Check>/262144 400ms ± 1% 391ms ± 1% -2.15% (p=0.000 n=20+18)
```
* Change format:
* previously there was a single link per talk, the video if available
* now there are separate "video" and "slide" links
* Adds link to video for 2024 CppNorth talk
* Adds link to slides for 2024 LLVM Developers' Meeting
* Restores links to slides from past years
---------
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
In preparation for further refactoring, switch away from member
functions for most of `ImportRefResolver`.
Split `ImportRefResolver` into a context class that exposes the value
stores for the source and destination files, and a derived class that
maintains a worklist. The idea is to statically enforce that functions
that take `ImportContext` cannot accidentally add new work, because they
don't have access to the work queue.
Adds `FacetAccessWitness` instruction and uses it in `member_access.cpp`
to support accessing members of facets. Still to do: interface witness
access is producing runtime values when it should produce symbolic
values.
---------
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Previously it would allow interface mismatches. We only need to support
the case where there is a single interface, though, which makes checking
much more straightforward.
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
- Rename TypedInstArgsInfo references to InstLikeTypeInfo. The type was
renamed in 07efa026de.
- Update and correct the link to search for ValueStore (and similar) in
the Context class. We must avoid the google-doc-style checks rewriting
`repo:` to `repository:` in the URL.
- Mention the existance of many types of Store collections now.
- Remove pre-C++20 idioms in Field detection. Correct the concept based
idioms to work.
- Fix code indenting consistency.
---------
Co-authored-by: Richard Smith <richard@metafoo.co.uk>