Fix segfault due to b64 encoding#919
Conversation
Prior to this patch, bconst.b64 encoded its instruction with a 32-bit immediate that caused improper decoding of the MOV instruction; fixes bytecodealliance#911.
|
can we avoid the 64-bit mov entirely here? since the immediate is either 0 or 1, it doesn't seem like we need to specify a 64bit destination register, and just rely on zero-extension to do its thing. I think that means an equally correct fix would be just removing |
|
@awortman-fastly, that makes sense to me and the test passes; let me try it that way and see if @bnjbvr has a strong opinion one way or another. If we don't want to use the 32-bit encoding we can revert 56f0733; otherwise we can squash when we merge. |
|
@awortman-fastly @abrown It's an elegant solution indeed! Unfortunately, since there's no REX variant with this solution, it means it restricts the possible output register to the 8 first registers in 64-bit mode. I think a proper fix is a mix of both: first the 8 bytes recipe with REX.W, and then after this the 32-bit immediate recipe. (REX must come first just so it's selected first by register allocation, with the fewer constraints on register assignment, and then the relaxation phase may try to use the 4 bytes recipe if that fits the operand constraints.) |
|
Ah, I'd misunderstood how (sorry for the back and forth on your small change @abrown!) |
|
I don't see an encoding for a |
So that the immediate can be 32bit. Implicit zero extension should take care of writing the right 64bit value into the register if I understand it correctly. |
|
Yeah, I think in the case of just wanting a 32-bit operand that makes sense, but just encode it as |
|
I do see this comment "Use of the REX.R prefix permits access to additional registers (R8-R15)" so perhaps that is what @awortman-fastly meant? [edit: never mind, I think that only applies to ModR/M bytes, which the immediate version of |
|
I think the manual only lists Section 3.1.1.1, edit: notably, edit2: said "postopt" in edit1, but meant "instruction shrinking" :) |
|
I think I see what you mean; you're aiming to make more registers available, right? (Agreed that the instruction table may not have all pairings). I do see the following on Table B-15 (page 2590) and perhaps you are trying to use the second of these? However, I don't see a good way to set the B bit on the REX byte in cranelift (not that that can't be fixed). |
|
Never mind, I just don't understand cranelift yet: I can see that the REX.B bit is correctly set for the current 64-bit immediate implementation. |
|
I can also verify that when I try to encode bconst.b64 without the |
|
REX.B is selected based on the operand register when the selected recipe is actually executed - that's handled by re. which encoding line, I meant the third one in fact! The fourth is what we get with |
|
@awortman-fastly, thanks; I think we are on the same page now. I implemented exactly that for the comment above and the emitted |
bnjbvr
left a comment
There was a problem hiding this comment.
Thank you both for the investigation and patch! Confirming that the REX.B bit is set automatically by the rex1 etc functions. Let's move the test to binary64 and add one that uses rax to make sure it works in both cases!
Prior to this patch, bconst.b64 encoded its instruction with a 32-bit immediate that caused improper decoding of the MOV instruction; fixes #911.