Change impls from `<interface>.impl` to `<self>.as.<interface>.impl`,
and *member* functions to `<parent scope>.<fn>` (non-member functions
exclude their parent scope). Stop special-casing builtin functions,
given the new naming scheme.
The purpose of this is to make it clearer when a member function is
being accessed and, if so, which member function. In particular, we
often access interface `Op` functions. The builtin function
special-casing was intended to help with that, but we still have lots of
`Op` functions. This particular approach should make the interactions
clearer.
This changes up queueing of block IDs a little because, in particular,
we need to process bodies of entities only after constants finish
processing. But, it should also result in less memory usage during
processing because it means we have less on the insts stack at any given
time, since we track a block rather than all instructions contained by
the block.
This changes `Destroy` to use an interface for its implementation.
Note that this change includes a lot of test updates. Even when
`Destroy` is a no-op, it still causes code generation as part of
determining that.
Originally I was trying to use ranges to cut down the scope of this, and
to a degree I think they have. But a flipside here is that cases where
no destructors should be generated -- particularly globals -- would be
needed to completely remove destructor calls. Even for ranges, the range
can often include the destructor placement. So I've shifted
frame-of-thought a little: accept a bunch of destructor churn, because
destructors are needed and will be prevalent. The verbosity is a feature
of the design to make desugaring apparent in IR, not a bug.
Adds min-preludes to a few more slowest tests, and adds them to most of
the lowering tests, with a few exceptions that make use of operators.
This take the runtime of file_test down from about 8s to about 7s on my
machine.
We add support for Negate on uints in the min-preludes.
In line with the proposal in #4682, this changes the array syntax to be
array(T, N). `array` is a builtin keyword which must be followed by
parens containing two expressions and a separating comma.
The array type expression is still fully builtin, it does not forward to
a Core.Array library type yet. It merely adds the `ArrayType`
instruction, as was done with the previous syntax.
Followup work will change the instruction to reference to Core.Array,
once the library type exists and can be used directly.
---------
Co-authored-by: zygoloid <richard@metafoo.co.uk>
- The actual reason I started this: minor lowering updates in the golden
LLVM IR
- Process.inc changed enough to need a patch context update.
- https://github.com/llvm/llvm-project/pull/123126 added `proto_library`
uses without a `load`, which is broken in bazel 8
- Just commenting these out because we don't use them. I'll follow up
separately about a possible fix, but continuing to use `WORKSPACE` is a
bigger issue LLVM probably should address.
- Note this update is also triggering removal of `migrate_cpp`, in #4887
Use a deque to maintain the set of instructions to be walked over. so
that the loop can append more instructions (with their related scope)
during iteration without requiring recursion.
---------
Co-authored-by: jonmeow <jperkins@google.com>
Non-entry-block allocas will allocate new stack memory each time they're
reached, resulting in leaking stack memory over time for allocas in a
loop. Move all such allocas to the entry block instead, and use an LLVM
intrinsic to mark when the lifetime of the variable actually begins.
Such indexing operations are created by array initialization. Since we
switched integer literals to be of type IntLiteral we've been attempting
to index arrays with the (empty) representation of an IntLiteral rather
than with an actual integer value.
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>
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>
This seems to be enough to avoid naming collisions for functions in any
of the current test cases (verified by asserting that the name of the
`llvm::Function` matches the name passed to create it - not triggering
LLVM's numbering that happens when names collide)
It currently implements mangling for namespace scopes, class scopes, and
impls.
Nothing generic is mangled yet - haven't looked at how that works,
though evidently it's not covered by existing testing, I guess.
Follow-up change will document the current mangling algorithm in
`toolchain/docs/lower.md`
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
There's not much mangling happening yet - but Run -> main (and some
overloading numbering happening, maybe LLVM is doing that 'helpfully'
under the hood?) is enough to demonstrate this improvement/fix.
Ah, here it is:
```
#0 llvm::ValueSymbolTable::makeUniqueName (this=0x50287fe5b6c0, V=0x50287fe827e8, UniqueName="F") at external/_main~llvm_project~llvm-project/llvm/lib/IR/ValueSymbolTable.cpp:45
#1 0x000055555c40f964 in llvm::ValueSymbolTable::reinsertValue (this=0x50287fe5b6c0, V=0x50287fe827e8) at external/_main~llvm_project~llvm-project/llvm/lib/IR/ValueSymbolTable.cpp:100
#2 0x000055555c2a91df in llvm::SymbolTableListTraits<llvm::Function>::addNodeToList (this=0x50287fd16f18, V=0x50287fe827e8) at external/_main~llvm_project~llvm-project/llvm/lib/IR/SymbolTableListTraitsImpl.h:75
#3 0x000055555c2a90e5 in llvm::iplist_impl<llvm::simple_ilist<llvm::Function>, llvm::SymbolTableListTraits<llvm::Function> >::insert (this=0x50287fd16f18, where=..., New=0x50287fe827e8)
at external/_main~llvm_project~llvm-project/llvm/include/llvm/ADT/ilist.h:166
#4 0x000055555c27fef2 in llvm::iplist_impl<llvm::simple_ilist<llvm::Function>, llvm::SymbolTableListTraits<llvm::Function> >::push_back (this=0x50287fd16f18, val=0x50287fe827e8) at external/_main~llvm_project~llvm-project/llvm/include/llvm/ADT/ilist.h:250
#5 0x000055555c27faeb in llvm::Function::Function (this=0x50287fe827e8, Ty=0x50287fd43058, Linkage=llvm::GlobalValue::ExternalLinkage, AddrSpace=0, name="F", ParentModule=0x50287fd16f00) at external/_main~llvm_project~llvm-project/llvm/lib/IR/Function.cpp:521
#6 0x0000555559441f95 in llvm::Function::Create (Ty=0x50287fd43058, Linkage=llvm::GlobalValue::ExternalLinkage, AddrSpace=0, N="F", M=0x50287fd16f00) at external/_main~llvm_project~llvm-project/llvm/include/llvm/IR/Function.h:175
#7 0x000055555c27ebac in llvm::Function::Create (Ty=0x50287fd43058, Linkage=llvm::GlobalValue::ExternalLinkage, N="F", M=...) at external/_main~llvm_project~llvm-project/llvm/lib/IR/Function.cpp:398
#8 0x0000555558ce7bb5 in Carbon::Lower::FileContext::BuildFunctionDecl (this=0x7fffffffc438, function_id=...) at toolchain/lower/file_context.cpp:257
```
That's where LLVM decides to make a new name (name.number) when asked to
create a new global with the same name as an existing global.
It's not a valid mangling scheme - since the name won't be stable
between different compilations, but it is enough to make
single-compilation code build/run for now.
Seems to work with lldb ( https://pastebin.com/igKkNECm ), though gdb
has /some/ trouble with the paths (they aren't complete - just using the
filename directly, not providing the working directory - might be some
quick hacks that can help there).
Refactors a bunch of the SemIRDiagnosticConverter to be able to use that
from Lower to access source locations there to use in debug info.
I assume some of this is a bit jank/would need to be fixed/improved in
the future - like the context functor that's passed into ConvertLoc?
(not totally clear what that's for/what the debug info will be missing
out on in its absence, I could throw a FIXME in there if you like)
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Still doesn't have line tables, so of limited value (at least now
this'll be enough that LLVM really generates debug info into the
resulting object file (whereas with only the compilation unit metadata,
LLVM will consider it empty and avoid emitting any of it)) - but another
step along the path.
This also doesn't attach the right source location to the functions -
I'll do that in a follow-up change because I think it'll require the
majority of the refactoring between driver and check to extract the
essential functionality sem_ir_diagnostic_converter, I think, to allow
retrieving source locations during lowering.
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This adds just the debug info metadata for Compilation Units (the top
level container of debug info) - but without anything in them, LLVM
won't emit them at all, so while this is testable at the IR level, it
isn't observable at the object level until more debug info is added.
A couple of starting points in this patch:
* A flag (`--debug-info`, seems to match the naming/style of other flags
in the carbon driver, though this is different from the naming
conventions of clang/gcc) that enables debug info when lowering. Open to
other names/approaches (on by default? historically debug info's been to
large/expensive to do this, so sticking with that precedent for now).
* Enabling that flag by default in the lowering tests - I do find the
churn on golden tests a bit rough, and adding more features to all the
tests means more churn, but it seems consistent with the approach so far
- keep an eye on this and perhaps revisit this if the churn gets too
annoying
---------
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This has is a nice-to-have for me. Frequently I want to run a specific
test, and end up digging through output to be able to copy-paste the run
line. This uses TIP lines to inject the command into the file when using
AUTOUPDATE.
Note, one of the reasons I want this is because "bazel test
//toolchain/testing:file_test --test_output=all" has been regularly
exceeding bazel's output limit for me (workaround is either opening the
output file or specifying an obscure output limit flag), making it a
little harder for me to get the commands. However, frequently I'm adding
a file and want to iterate on it, so that's really the use case I have
in mind here.
Factor out `SemIR::InstNamer` and also use it when lowering to LLVM IR.
Automatically name all instructions created with our `IRBuilder` based
on the name computed by the `InstNamer`, and likewise name basic blocks
using the label generated by the `InstNamer`.
Move some of the existing naming logic out from lower into `InstNamer`
so that it's also used in SemIR. In particular, we now name call
instructions after their callee, or after the builtin name for calls to
builtins.
Computing and adding these names isn't completely free. This instruction
naming is designed to be optional, so that we can turn it off for builds
where the LLVM IR will only be converted to assembly and won't be seen
by a human, but so far it's enabled unconditionally. We can tune that
later as needed.
Fix a bug where we would perform the computation of the return location
in SemIR after we have already used it in some cases, leading to
assertion failures during lowering. Instead, accumulate a sequence of
instructions to compute the return location in a temporary block, and
overwrite the return slot with those instructions when we perform
initialization.
StubReference is replaced by a more general SpliceBlock node, that takes
a code block and a result value, executes the instructions in the block,
and produces the result. This is used in the uncommon case where more
than one instruction is required to compute the return slot, which can
happen if we need to first emit a temporary and then index into it, or
if we need to perform multiple levels of indexing before we reach an
entity to initialize.