For `Assign` and `ReturnExpression`, this field wasn't used for
anything. For `StructTypeField`, we stored the type of the field here,
and now store it as an argument of the node instead.
---------
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Lowering for tuple with a workaround for typetype. I don't think this
will generate tuple objects with correct values for the typetype issue.
---------
Co-authored-by: Farzana Ahmed Siddique <fasiddique@google.com>
This shifts logic so that bindings are added to name lookup only after the scope is complete, removing logic around adding/removing/re-adding names in certain scopes.
This does mean that things like a function's forward declaration will need to go through an extra hoop for name conflict checks, because under this approach a function definition does conflict checking when it adds names for the body's use. But, that seems easy to address, and better than the current hoops.
The "locals" naming is intended to reflect that I haven't really thought through how globals work, but suspect they're going to end up at least partially separated. Stepping away from the "node" naming feels like it'll reduce confusion, although maybe "values" might be better? (but values seems imperfect in the presence of globals)
The map is the more important part here; I want to avoid anchoring on the prior vector approach.
Start inserting loads when getting a value. This is done conditionally, but in theory we could start tracking nodes which need loading differently if the `isa` is considered cumbersome.
As I've worked on this more, it's just felt verbosely redundant -- lowered should be the default assumption, needing no further explanation. This does mean there's `context.GetType()` and `context.semantics_ir().GetType()`, but I feel like that's still reasonably clear on reading.
This switches types to using SemanticsTypeId instead of SemanticsNodeId, and lowering pre-builds its list of types. The empty tuple type is special-cased because we don't want to emit it unless it's in-use, but as the implicit return for functions, it's frequently used. Callables use invalid to indicate the implicit return, and that seems undesirable to change due to the size increase.
We do use the empty tuple type for function returns, so I don't want to get rid of it, but the value is unused. With this change, builtins are all types. Long-term the empty tuple value should have a representation similar to structs; just a tuple value that's empty, not a built-in.
This removes special-casing of empty structs, handling them as just a regular value instead of a builtin. Note the `{} as Type` is still special-cased.
In lowering, removes the test of calling a function using `{}` because it's missing the proper load/store. This setup notices that error whereas the prior worked due to said special-casing. Fixing this will need to be done as part of generally adding loads for variable uses.
I'm not sure this is really the best approach, as noted by the TODO. While it does reduce the generated IR in many cases (especially if we start eliding `()` in favor of void), it increases the amount of code in a common function which may have higher impact on performance. I was leaning towards the idea that review would favor the former for now, lacking benchmarking supporting adding unused content to the IR.
This is addressing an issue left behind by the context switch, removing a few diagnostics that had been in the header rather than figuring out proper homes. I'm splitting one for semis a little further, sharing one, and then the other two are actually able to be moved into more specific homes as-is (one is only used in one place, clearly an oversight that it wasn't there already).
This adds names for more LLVM IR entries. For now, `var` is just a placeholder due to the difficulty of associating a name, but the rest reasonably reflect intent.
I'm trying to comment logic for this because I suspect we'll want to make it more conditional later. Even though chandlerc noted the expectation that IRBuilder would have a way to disable them in output, that's fine for things like anonymous names; other places they'll still take extra work to calculate. e.g., as with struct fields where the type's fields are only fetched to print a name, not otherwise needed for the gep.
Previously, IR for arguments in calls and struct values was separated out. This merges it back in. Additionally, parameters for functions and struct types had their own IR; the block is still there, but there's a TODO to decide what to do with it.
In the LLVM IR, this has the consequence of emitting expressions that are inputs to a call or struct value within the scope of the function, which is pretty much where it should be. Importantly it happens before the call is encountered.
This change also tinkers with the int and real literal lowering. I'm pretty sure both are still wrong, but was having trouble figuring out a "better" way to do it, and this seems like it'll work for now.
This currently handles most of struct types and member access, but not values. The value issue is, I think, an underlying semantic IR approach (changed in #2824). I'd still like to get this in in order to ensure I'm creating IR at least reasonably well, but I want to be clear this is expected to be incomplete and is split out mainly to try to keep PRs in reasonable units.
This echoes https://github.com/carbon-language/carbon-lang/pull/2818 and the philosophy is mostly covered there.
This isn't necessary for lowering right now, but things are likely to head in that direction and maintaining the context boundary will reduce blurring of lines. For now I'm just putting all the handlers in one file.