Canonical way to create back edges

Continuing the discussion from this PR, comments reproduced below:

Code comment:

// Unwrap the channel. The ready signal is a Value we haven't created yet, so
// create a temp value and replace it later. Give this constant an odd-looking
// type to make debugging easier.

Me: Is this the correct way to create back edges? Feels kinda hacky but it works.

@clattner This is sort of weird but I can’t think of a better way to do this off-hand.

@mikeurbach Could you do something like the following?

Value val;
...
[use `val` as needed]
...
val = [code to create value]

[cont’d] I’m guessing passing around a null Value might not work and this temp constant was needed?

Me: Spot on.

I’m thinking we could create an Op which we exclusively use to create back edges. We could then create a class which uses RAII to build the operation, then does some checking and cleans up after itself upon destruction. Does this sound like a good idea?

I think it’s an interesting idea. Worth trying.

Yeah makes sense to me!

The cursor variable is a similar thing in FIRRTLModuleLowering::lowerModuleBody. It is using the op as an iterator marker sort of thing temporarily, then deleting it after it is done. It seems like a different use case for exactly the same sort of thing you’re talking about.

Backedge creation utility classes by teqdruid · Pull Request #333 · llvm/circt (github.com)

@clattner Yep, it’s like cursor but a little more involved.