This has subtle effects on the number of imported instructions, but
seems more standard for how this code is being written...
`GetLocalConstantId` calls `GetLocalConstantValueOrPush` which does
`local_constant_values_for_import_insts().GetAttached`. So what this is
really doing is causing some intermediate import steps to be skipped.
But per test changes, that doesn't really affect SemIR and will probably
have negligible effect. This *seems* right to me, otherwise I'd expect
we should probably refactor all `GetLocalConstantId(InstId)` calls.
When we `impl as Z` and `Z` is an interface with a require relationship
to another interface `Y`, we produce an error at the definition if the
self type does not impl the required interface `Y`.
The require relationship need not be satisfied yet at the declaration of
the `impl as Z`, and a declaration of `impl as Y` is enough to write the
definition of `impl as Z`.
They are not used for impl lookup or verifying anything yet, but now
they appear in the textual semir.
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
The `RequireDecl` instruction points, via a `RequireImplsId` to a
`RequireImpls` structure in a `ValueStore`. That structure holds the
self-type and facet type, as well as the generic id and parent scope.
`RequireImpls` is always a generic since it only appears in an
`interface` or `constraint`, which both have a generic parameter `Self`
applied to all their members.
The `RequireDecl` instruction evaluates to itself, but drops the
decl_block_id since the instructions within the `require` declaration
are not required in the canonical value which is only used for import.
And import will want to import the `RequireImpls` structure along with
the `Interface` or `NamedConstraint` structure it is in, rather than
recreate it from the decl's instructions. This also avoids repeating all
the instructions within the `require` decl in the textual semir's
constants block.
Adding the `RequireImpls` to the `Interface` or `NamedConstraint`
structure is not yet done, so they are not available for impl lookup or
import yet.
Adds support for object-like macros with a single replacement
numeric-literal kind token. Only macros that evaluate to an integer
constant are supported for now. When detected at name lookup, they are
imported as a constant integer value in Carbon.
Demo:
```c++
// --- macros.h
#define CONFIG_VALUE 2
```
``` c++
// main.carbon
library "Main";
import Cpp library "macros.h";
import Core library "io";
fn Run() {
let a: i32 = Cpp.CONFIG_VALUE;
Core.Print(a);
}
```
```c++
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link main.o \--output=demo_carbon
$ ./demo_carbon
2
```
Part of #6303
Most inputs are matched against the current regex. An input that starts
and ends with `/` sets a new regex instead. EOF terminates the program.
---------
Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
This unit test uses "using UEnum = Enum;" and imports that into Carbon.
This is my very first try at contributing something to carbon, I'm
looking forward to your feedback.
The test is very basic.
What other cases should it test ?
What other comments do you have ?
Do this even if the operand is a `ConstType` instruction. This better
preserves the source form of the type, and avoids a special case.
Repeated `const`s are already flattened in constant evaluation, and this
special case also didn't prevent forming a `ConstType` whose operand is
`const` in general, only cases where the operand happens to literally be
a `ConstType` instruction.
This reverts commit eed21f6439.
Completing a pointer type is trivial, but we still need to do it, and
fail to do so in a few places, which can lead to crashes during
lowering. Switch to completing pointer types when the type is created to
avoid the issue.
Format the entity name into the instruction name for a FacetAccessType
of a SymbolicBinding. This means (T as type) gets formatted as
`T.as_type` instead of just as `as_type` for the non-canonical
FacetAccessType instruction. The same is already true for the canonical
SymbolicBindingType.
If the value representation of `T` is a copy representation, but it
copies all of the bits of `T`'s object representation, then it's OK to
use that as the value representation of `MaybeUnformed(T)` too.
This fixes the behavior of interop with nullable pointers, which are
represented as an adapter of `MaybeUnformed(T*)`, and need to be passed
to and returned from functions on the Carbon / C++ boundary as `T*`s.
Adds support to the `dump` debugger command for named constraint ids,
which are printed as `constraint<number>`. While doing so, we print
whether the `constraint` is complete or not, and add the same to
`interface` to match.
And we noticed that the printing of name and name scope ids, which are
not tagged, are very verbose by adding 7 `0`s to them for no reason. So
make the dump output easier to read by dropping 0 prefixes.
Before:
```
name_scope00000000: {inst: inst0000000E, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name00000000: inst6000000F, name00000001: inst60000011}} {kind: Namespace, arg0: name_scope00000000, arg1: inst<none>, type: type(inst(NamespaceType))} `package`
```
After:
```
name_scope0: {inst: instE, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name0: inst6000000F, name1: inst60000011}} {kind: Namespace, arg0: name_scope0, arg1: inst<none>, type: type(inst(NamespaceType))} `package`
```
This turns `Cpp` into a keyword, and makes it map to `NameId::Cpp` and
`PackageNameId::Cpp`.
Per discussion with zygoloid, the keyword versus identifier question is
deliberately kept open by #4846. This PR switches to a keyword because
mapping to a specific `PackageNameId` works best with a special `NameId`
not backed by an `IdentifierId`. We could in theory make it work using
`IdentifierId` or a runtime-tracked `PackageNameId` for `Cpp` (e.g.
stored on `SemIR::File`), but this approach is consistent with `Core`
and so seemed like a good starting point.
---------
Co-authored-by: Dana Jansens <danakj@orodu.net>
If `T` implicitly converts to `U`, then:
* `const T` implicitly converts to `U`,
* `T` implicitly converts to `const U`, and
* `T` implicitly converts to `Optional(U)`.
Adds a flag `--optimize=<mode>` that specifies what to optimize for:
* `--optimize=none` turns off the optimizer as much as possible, but
still respects always_inline.
* `--optimize=debug` aims to be the equivalent of `-Og` / `-O1`, and
provides optimizations that don't affect the ability to debug the
program. This is the default.
* `--optimize=size` optimizes for the size of the produced program, and
aims to be the equivalent of `-Oz`.
* `--optimize=speed` optimizes for the execution time of the produced
program, and aims to be the equivalent of `-O3`.
Following the approach taken by Clang, the optimization level feeds into
both the configuration of the LLVM pass pipeline and the attributes
added to function definitions generated by the frontend.
Optimization is performed in a new phase, `optimize`, which runs between
`lower` and `codegen`.
---------
Co-authored-by: Dana Jansens <danakj@orodu.net>
Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
I was thinking that the incompleteness diagnostic for C++ types would've
been produced by Clang for record types, but seems they're produced by
Carbon & we already /are/ sharing that diagnostic (with #6302), and that
patch only adds an extra note rather than being a whole separate
codepath for effectively the same diagnostic.
As a byproduct, the only test that exercised the "address of a temporary
object" diagnostic now trigers the "address of a non-reference
expression" diagnostic. We could restore it by using a type that doesn't
support `value_of_initializer`, but it seems better to remove the
diagnostic altogether: not only does it simplify the code, I'd also
argue "non-reference expression" is more accurate as a user-facing
description of the operand.
This imports the entire `NamedConstraint` structure when importing
`NamedConstraintDecl`. This will be required to identify a facet type
that contains a named constraint, as we will need to pull the `require`
decls out of the `NamedConstraint` structure to do so.
I tried making the `InterfaceDecl` code path
[templated](https://github.com/carbon-language/carbon-lang/pull/6308#discussion_r2482655927)
to reuse it, but it was a lot of template parameters including field
pointers into `InterfaceDecl`, `GenericInterfaceType`,
`SpecificInterface`, and it was very hard to read so I gave up on that
approach here.
This requires declared FacetTypes to hold NamedConstraintIds (along with
a specific) that are named in an extend or impls requirement. We add
support to stringify and formatter to display the named constraints in
the facet type, and special case when a facet type contains a single
extend named constraint, like we did for a single extend interface.
This means that `RequireIndentifiedFacetType` can now fail, if the facet
type contains a forward-declared named constraint. Add the appropriate
diagnostics for each call to this function, and note the ones that
should change to `RequireCompleteFacetType` in the future with TODOs.
We also add tests for using facet types that can or can't be identified,
or completed, with named constraints in them.
They don't get stored anywhere yet, but this type checks the
declarations and diagnoses errors in their form, such as not placing a
facet type after `impls` or a type before it.
#6289 absentmindedly added fields in more places, and this is undoing
that plus further fixes.
This does some cleanup of types with relation to singletons. For
`TypeType` and `ErrorInst`, they're always complete due to a
`SetComplete` call in `file.cpp`. For `CppVoidType`, it's intended to be
incomplete by construction, and so a `TypeId` should be okay. The intent
though on not generally providing these had been that `GetSingletonType`
needs to be called to get a type to be marked as complete.
In the case of `AutoType`, removing `TypeId`does change a small printing
detail. I think that's old legacy that's just been carried forward.
Otherwise, for both `InstType` and `AutoType`, I've added
`GetSingletonType` calls where they were used in order to ensure
completeness is applied correctly. These calls cause small SemIR
permutations.
This causes `AutoType` to be seen by lowering, so I'm adding a
placeholder for it. Also merging two functions that look like they're
identical in intent -- not sure why they're separate.
---------
Co-authored-by: Dana Jansens <danakj@orodu.net>
We give `Self` in an interface/constraint a location so it's not elided
when trying to dump the interface/constraint. We use the location of the
start of the definition, which is the scope for which the `Self` is
constructed and is available in.
The error message was saying "generic interface" but should say "generic
constraint"
There is one test that demonstrates the error message for interfaces,
but it's in tests for overloads, so add a more clearly dedicated test
for interface too.
Currently we schedule work on the CppOverloadSet but then never `Add()`
it to add its contents to be fingerprinted, and just immediately return
an empty fingerprint.
Use CARBON_KIND_SWITCH to prevent this sort of thing from happening in
the future, now that we can use it for std::variant.
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
`ImplWitnessTablePlaceholder` is the only non-type singleton instruction
(`ErrorInst` is a type; while `ImplWitnessTablePlaceholder` exposes
`TypeInstId`, it's only used as an `InstId`).
In order to allow simpler handling of singleton instructions, replace
`ImplWitnessTablePlaceholder::TypeInstId` uses with
`InstId::ImplWitnessTablePlaceholder`. Since the placeholder instruction
was never evaluated, this has no significant effect on behavior.
---------
Co-authored-by: Dana Jansens <danakj@orodu.net>
This is just reducing boilerplate in `typed_insts.h` because we have a
number of singleton types, and keep adding more.
The changes to `TemplateString` allow `TemplateString IrName` to be used
as a `StringLiteral`.
---------
Co-authored-by: Dana Jansens <danakj@orodu.net>
This defines `Cpp.void` as a custom type.
`Cpp.void*` is mapped to C++ `void*`.
Not supported yet: Conversions from and to other pointer types.
C++ Interop Demo:
```carbon
// main.carbon
library "Main";
import Core library "io";
import Cpp inline '''
#include <cstdio>
auto GetPointer() -> void* _Nonnull {
static int x = 8;
return &x;
}
auto GetValue(void* _Nonnull ptr) -> int {
return *static_cast<int*>(ptr);
}
''';
fn Run() -> i32 {
let ptr: Cpp.void* = Cpp.GetPointer();
Core.Print(Cpp.GetValue(ptr));
return 0;
}
```
```shell
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link main.o --output=demo
$ ./demo
8
```
Part of #6280.