Commit Graph
28 Commits
Author SHA1 Message Date
Richard Smith 7d8d59cb7e Make snegate / unegate overflow handling consistent with other builtins. (#4744)
Make `int.snegate` ignore the signedness of its operand and
unconditionally check for signed overflow like all the other `int.s*`
builtins do. Fix the prelude implementation of unary `-` for `Core.UInt`
to use `int.unegate` instead of `int.snegate`.

Fix the test for unsigned negate to actually test negating unsigned
integers, and add some tests that unary `-` also works.
2024-12-26 22:07:47 +00:00
Dana Jansens 9290ee2bcf Use unsigned arithmetic builtins for UInt(N) operations (#4740)
We were mistakenly using the signed builtins, which produce the same
lowering for add/multiply right now, but don't for division and modulus.

When manually flipping SignedOverflowIsUB on, the signed version of add
gains the nsw (no signed wrap) flag, while the unsigned version
(correctly after this change) does not:
```
// CHECK:STDOUT: define i32 @_Cadd_i32.Main(i32 %a, i32 %b) !dbg !4 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT:   %int.sadd = add nsw i32 %a, %b, !dbg !7
// CHECK:STDOUT:   ret i32 %int.sadd, !dbg !8
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @_Cadd_u32.Main(i32 %a, i32 %b) !dbg !9 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT:   %int.uadd = add i32 %a, %b, !dbg !10
// CHECK:STDOUT:   ret i32 %int.uadd, !dbg !11
// CHECK:STDOUT: }
```
2024-12-26 00:36:33 +00:00
Richard Smith c04d62a7d1 Ensure that all allocas are created in the entry block. (#4685)
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.
2024-12-17 00:55:06 +00:00
josh11bandJosh L 5d1b39e1f2 More instructions get named (#4615)
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>
2024-12-03 20:47:53 +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
Richard Smith bc395eb889 Represent integer literals as IntLiteral not as i32. (#4532)
When an `IntLiteral` appears as an operand of an `if` expression,
convert it to `i32` for now, so that we don't reject things like `if
cond then 1 else 2` due to having a non-constant value of type
`IntLiteral`.

For tuple indexing expressions such as `(a, b).0`, convert the index to
type `IntLiteral`, not to type `i32`. This isn't strictly necessary to
do in this PR, but avoids the need to provide an `IntLiteral` -> `i32`
implicit conversion for `no_prelude` tests using this syntax.
2024-11-15 23:24:15 +00:00
David BlaikieandJon Ross-Perkins 4631767943 Stop name mangling at an imported package name (#4294)
To ensure the outer package name is not mangled into imported names.

With this change I can successfully link/run a two-file example:
```
package Mod;
fn HelloWorld() {
  Core.Print(42);
}
```
```
import Mod;
fn Run() -> i32 {
  Mod.HelloWorld();
  return 0;
}
```
```
$ carbon compile mod.carbon main.carbon
$ carbon link mod.o main.o --output=a.out
$ ./a.out
42
```
\o/

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-09-18 22:01:08 +00:00
a548eff0bb Rudimentary name mangling support (#4267)
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>
2024-09-06 23:10:21 +00:00
Richard Smith 16fd645663 Add source locations to interface_witness and interface_witness_access instructions. (#4265) 2024-08-28 23:30:00 +00:00
David Blaikie 67b287a2f2 DebugInfo: Add the name as-written, separate from the mangled name (#4253)
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.
2024-08-28 19:18:54 +00:00
David Blaikie 0ae2a3907e Add line-level debug info (#4247)
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).
2024-08-26 15:49:31 +00:00
David BlaikieandJon Ross-Perkins c5ada29ba9 Add filename and line number to function debug info metadata (#4243)
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>
2024-08-23 00:05:26 +00:00
David BlaikieandJon Ross-Perkins ea8ad22a17 Add function debug info descriptions (#4233)
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>
2024-08-22 17:19:30 +00:00
d57aa57215 Add rudimentry debug info metadata emission (#4225)
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>
2024-08-20 20:00:35 +00:00
josh11bandJosh L bfe0fc7cc8 Update to a recent LLVM version and the changes to LLVM IR. (#4212)
Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2024-08-12 22:29:33 +00:00
Jon Ross-Perkins 83413479d7 Move some of the test information to TIP lines (#4007)
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.
2024-06-04 17:57:23 +00:00
Jon Ross-Perkins 3561ab5fae Switch the prelude to using 'export import'. (#3976)
Note, I assume this doesn't affect all the TODOs (like for i32.carbon),
but does cut some things down (and requires updating some tests that
have prelude name conflicts, but I think they were intended to be
updated this way).
2024-05-22 22:55:31 +00:00
Richard Smith 23f9065949 Implement proposal #3927. (#3963)
Change syntax for package declaration to put the `impl` keyword at the
start and remove the `api` keyword.

To support this, rearrange processing of package, library, and import
declarations to use the general modifier handling support in declaration
parsing rather than special-case logic.

There is an ambiguity in `impl package.Foo as Bar`, which we resolve by
treating `package` as an introducer after a modifier only if it's not
followed by `.`.
2024-05-21 00:36:03 +00:00
Richard Smith 008d41d7f3 Move instruction names for struct and tuple values from lower to InstNamer. (#3918)
Change the names for emitted globals for constants with storage to
include both the name of the constant and the name of the use.

This causes the instructions to also be named in SemIR and in LLVM IR
constants.
2024-04-26 23:47:08 +00:00
79c0b65288 Separate constant emission from function emission. (#3916)
Make constant emission non-recursive, and stop building a bogus
FunctionContext to emit constants.

To support this, move `InstConstantKind` from the typed instruction
definition into the `.def` file, and add more macros to allow us to
generate case labels based on whether an instruction is a constant.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
2024-04-26 23:27:07 +00:00
Richard Smith ccf87f0a38 Use computed constants in lowering rather than lowering instructions (#3905)
First steps towards using constant values in lowering.

For now, we reuse the regular instruction lowering to lower constants.
This mostly works, because we don't actually need an `llvm::Function` or
a current basic block when lowering a constant most of the time.
However, a special case is needed for lowering aggregate value constants
because they would otherwise create a stack alloca to store the
constant. Separate constant lowering code will be added in a future
change to clean this up.

When lowering a constant initializing expression, the result is a value
of the destination type, rather than code to initialize the destination,
so a separate copy step is required when finishing initialization from a
constant for a type that uses in-place initialization. Handling this
required extending `ReturnExpr` to track its destination location.

We currently often create non-constant `*_access` SemIR instructions
that are only used by constant `*_init` instructions. These cause
lowering to leave behind `getelementptr` instructions in the lowered IR
that are now unused. It should be possible to detect this case and avoid
producing these instructions, or to produce them lazily, but for now
we're just leaving them around for LLVM to clean up.
2024-04-23 16:23:24 +00:00
Richard Smith 3776c068de Unify instruction naming between SemIR and LLVM IR (#3898)
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.
2024-04-19 02:19:30 +00:00
Richard SmithandJon Ross-Perkins d8be774b8b Lowering support for overloaded operators. (#3798)
Fix a collection of issues that were preventing lowering for overloaded
operators from working.

Instead of creating `import_ref` instructions during name lookup in the
current block, whatever that might be, we now create them in the `file`
block always. This avoids inserting them into blocks that might not be
intended to contain them, such as functions, and avoids the IR generated
for a function depending on which names we happen to have looked up
first.

When importing a class, function, or interface, import its enclosing
scope ID. This is necessary to allow us to distinguish between functions
at interface scope, which shouldn't be lowered, and other functions, and
will also be used in future to provide qualified names for declarations
when printing types. In order to support this:

- Track the constant values of namespaces created during importing so
that we can find them when resolving an import ref. Use those constant
values to convert an enclosing scope ID from the imported IR into a
corresponding ID in the current IR.
- Change how we do two-pass import of classes and namespaces so that we
can do two-pass import even for non-defining declarations, so that we
can import the enclosing scope.

While working on the final point above, I reworked `TryResolveInst` to
return a flag indicating whether another pass is necessary instead of
implicitly encoding this in the `ConstantId`. This permits the handling
of classes to be simplified; now `import_ir_constant_values` is only
accessed in a single place.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-03-20 23:32:44 +00:00
Richard Smith 428d11323a Directly convert from an initializer to a value where possible. (#3306)
If the initializing representation is the same as the value
representation, don't materialize a temporary and perform a value
binding. Instead, directly extract the value, using a new
`value_of_initializer` node.

This removes a lot of redundant `alloca`s from our generated LLVM IR.
2023-10-31 20:59:28 +00:00
Richard Smith 31d55da403 Stop creating fake integer literals as indexes for tuple initialization. (#3248)
This makes struct and tuple initialization basically identical; unify
them.
2023-09-21 00:41:19 +00:00
Richard Smith 842b471e67 Perform in-place initialization for tuples and structs (#3246)
This implements initializing expression semantics for structs and
tuples, following #2006 and discussions since.

Tuple and (and analogously, struct) literals are treated as having a
mixed expression category that is later resolved based on how the
literal is used, as either a tuple initializer or a tuple value, at
which point we create a `TupleInit` or `TupleValue` that represents the
formation of the tuple initializer or tuple value from the tuple
literal.

There's quite a lot of TODOs here, and the SemIR representation is still
not quite right, but this seems like a good place to checkpoint some
incremental progress.
2023-09-20 21:20:14 +00:00
Richard Smith 06d9813821 Fix lowering of 8 and 9. (#3200)
IntegerLiterals are not signed, so get the zero-extended value rather
than the sign-extended value. Sometimes we use the high bit of the
`APInt`, though currently this only happens for the literals 8 and 9 due
to the way we convert decimal integers to binary.
2023-09-06 21:30:29 +00:00
Jon Ross-Perkins ec307b18d8 Rename the lowering dir to lower (#3172)
This is continuing with #3070, starting dir renaming with lowering
because it's at the tip. AFAICT git is catching all the file moves.
2023-08-31 15:59:49 +00:00