According to the changed spec, rethrow now takes not an i32 immediate
but an except_ref argument. This patch deletes the old i32imm argument,
and does not add the except_ref argument because the argument will be
added after instruction selection.
Details
- Reviewers
dschuff
Diff Detail
- Repository
- rL LLVM
- Build Status
Buildable 15418 Build 15418: arc lint + arc unit
Event Timeline
Why do we need to omit the argument here? I'm not sure I understand what you mean by adding it after isel. Can/should a pass add an argument that doesn't match the format in the td?
Yeah, I agree this is ugly.. but don't know how to get around it. The argument of rethrow is an except_ref value, which cannot be represented in LLVM IR. So when lowering rethrow intrinsic into rethrow instruction, if we want to add the except_ref argument to the td file, we need a dummy argument, something like nullref, to insert. Before, rethrow used to take an integer (relative depth), so we initialized the argument with 0 when lowering it, as follows:
def : Pat<(int_wasm_rethrow), (RETHROW 0)>;
But now, we don't have a zero-like value in except_ref type, like 0 above, to initialize the lowered instruction with. That's the reason I omitted the argument in the td file. Do you think we can make a zero-like dummy value for this purpose?
I think we can add arguments that are not in the td file. For example, in the td file, br and br_if takes bb_op, but CFGStackify deletes all of them and adds an immediate (relative depth) instead.
I forget what the spec says right now, but I think we will need a null value for except_ref in the spec anyway, because locals are implicitly initialized to their respective 0 values. So we'd need a corresponding 0 value for ref types. So I think it would be fine to have a nullref type in LLVM too.
I did a quick search on existing td files but don't know how to add a null value for a custom type. Do you know how?
BTW Rossberg said they are NOT going to add nullref to except_ref or anyref type. (WebAssembly/exception-handling#55) I still think it is worthwhile to add it to LLVM backend for the instruction selection though.
Hm, another option could be undef here. I don't know if that would be any easier though.
Turns out it's not even a nullref or tablegen problem. (I mean, for rethrow instruction selection here. We certainly need nullref in wasm.)
What does it mean that we have a nullref value? Every MachineOperand should either be a register or an immediate. except_ref value cannot be an immediate, so it should be in a register.
Making a fake physical register, using it as an operand to rethrow in instruction selection, and registering it as a function live-in does not work, because PrepareForLivenessIntervals pass, which creates IMPLICIT_DEF for reg uses without defs, runs after ReplacePhysRegs pass. So we wouldn't even be able to figure out that was once a live-in physical register.
So we somehow have to put nullref, or whatever value, in a register ourselves. To do that, there should be a way to create it. At this point what we need is not even a nullref, because it is now actually irrelevant. The only thing that's relevant is how we create whatever value that is. That is dependent on where we put rethrow instruction. If we put that in a library function, that means ARGUMENT_EXCEPT_REF instruction will take care of it. If we put that with catch instruction, that catch will take care of it, but in this case rethrow instruction without a catch instruction will be invalid. For the prototype, I was not gonna put rethrow within a library function because that's easier and we wouldn't need to figure out how to pass except_ref as arguments. So, in this case, to land this, we need instruction selection patch that creates this value as well. But I marked the isel patch (D44090) as "Changes Planned" for now because we are likely to change that patch if we use WinEH.
So, in conclusion, it looks like we should put off landing this as well.
We don't actually create uses without reaching defs though, do we? Isn't it true that by the time we run PrepareForLiveIntervals, we've lowered the catch (and the catch will create a def of the phys reg that reaches the rethrow?)
Sure, but once everything is in, then we shouldn't have the problem that we get undefs created. So we coudl just roll this into whatever CL adds the defs.