We allow non-relaxable instructions emitted into relaxable Fragment when we prefix padding branch. So we need to check if the instruction need relaxation before relaxing it. Without this patch, it currently triggers a report_fatal_error in llvm::MCAsmBackend::relaxInstruction when we prefix padding branch along with --mc-relax-all.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Best to state that this currently triggers a report_fatal_error in llvm::MCAsmBackend::relaxInstruction.
llvm/test/MC/X86/align-branch-64-relax-all.s | ||
---|---|---|
2 | You can actually strip -pc-linux-gnu. ELF is the default. |
llvm/test/MC/X86/align-branch-64-relax-all.s | ||
---|---|---|
2 | Thanks for the suggestion. I plan to strip all the -pc-linux-gnu and the blank before # RUN in the test files align-branch-* after landing this patch. |
It seems that this change breaks the RISCV backend. RISCVAsmBackend::relaxInstruction assumes that the Relaxed parameter is a fresh uninitialized MCInst. With this change, invalid instructions with too many operands are generated. A similar problem probably happens for the Hexagon and for the AMDGPU backend.
/cc @asb also FYI that this breaks the RISCV backend.
yeah, I got your point. We may need to add a lit test to gurantee this assumption will not be broken.
We can fix this in two ways
- Change the control flow in MCObjectStreamer.cpp
- or create a fresh uninitialized MCInst at the beginning of RISCVAsmBackend::relaxInstruction, and after relaxation, assign its value to Relaxed at the end of RISCVAsmBackend::relaxInstruction.
Which way do you think is better? Personally, I prefer the second one, since getAssembler().getBackend().relaxInstruction(Relaxed, STI, Relaxed) is called in a loop, the assumption that third argument of relaxInstruction is a fresh uninitialized MCInst is very strange.
A special case is probably also needed for the Hexagon and AMDGPU backend, which does similar stuff in their relaxInstruction implementation than the RISC-V backend.
Is their any reason why relaxInstruction takes three argurments? Since relaxed is given in two arguments which are aliased to the same variable, I would drop the third argument and let relaxInstruction to either modify the given instruction or assign it to a fresh one (RISC-V, Hexagon, AMDGPU case).
https://bugs.llvm.org/show_bug.cgi?id=45580
this broke our Linux kernel builds of RISCV, too.
Has this been reverted? I see discussion of a fix being worked on, but has the change which triggered problems been reverted? I can't tell easily from the review history.
llvm/lib/MC/MCObjectStreamer.cpp | ||
---|---|---|
404 | If target expected "Relaxed" be a fresh MCInst, then this line also has problem. I think for RISC-V, this line isn't been executed, so the problem is not exposed before. I prefer to fix the bug in MCObjectStreamer.cpp, because some other target may also append new operand to Relaxed MCInst. And the relaxInstruction() API seems imply the Relaxed MCInst is fresh. while (getAssembler().getBackend().mayNeedRelaxation(Inst, STI)) { MCInst Relaxed; getAssembler().getBackend().relaxInstruction(Inst, STI, Relaxed); Inst = Relaxed; } |
llvm/lib/MC/MCObjectStreamer.cpp | ||
---|---|---|
404 | The code you paste doesn't make sense, Inst is a const MCInst &. |
If target expected "Relaxed" be a fresh MCInst, then this line also has problem. I think for RISC-V, this line isn't been executed, so the problem is not exposed before. I prefer to fix the bug in MCObjectStreamer.cpp, because some other target may also append new operand to Relaxed MCInst. And the relaxInstruction() API seems imply the Relaxed MCInst is fresh.