Skip to content

Conversation

@Bajtazar
Copy link
Contributor

Fixed bug introduced by #96057 which could crash the disasm when the non-labeled branch was given

Note. To fully resolve the issue the major changes in the riscv emitter have to be done so this PR is just a quickfix to remove crashes

Some of the working non-labeled jump print sample:

            addi           t1, t1, -1
            addi           t0, t0, 16
            bne            t1, zero, pc-16 (-4 instructions)
            addi           t0, sp, 304
            sd             t0, 296(fp)

Part of #84834
cc @wscho77 @HJLeee @clamp03 @JongHeonChoi @t-mustafin @gbalykov @viewizard @ashaurtaev @brucehoult @sirntar @yurai007 @tomeksowi

@ghost ghost added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI community-contribution Indicates that the PR has been added by a community member labels Dec 18, 2023
@ghost
Copy link

ghost commented Dec 18, 2023

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixed bug introduced by #96057 which could crash the disasm when the non-labeled branch was given

Note. To fully resolve the issue the major changes in the riscv emitter have to be done so this PR is just a quickfix to remove crashes

Some of the working non-labeled jump print sample:

            addi           t1, t1, -1
            addi           t0, t0, 16
            bne            t1, zero, pc-16 (-4 instructions)
            addi           t0, sp, 304
            sd             t0, 296(fp)

Part of #84834
cc @wscho77 @HJLeee @clamp03 @JongHeonChoi @t-mustafin @gbalykov @viewizard @ashaurtaev @brucehoult @sirntar @yurai007 @tomeksowi

Author: Bajtazar
Assignees: -
Labels:

area-CodeGen-coreclr, community-contribution

Milestone: -

unsigned int iiaEncodedInstr; // instruction's binary encoding.
regNumber _idReg3 : REGNUM_BITS;
regNumber _idReg4 : REGNUM_BITS;
unsigned int iiaEncodedInstr; // instruction's binary encoding.
Copy link
Member

@tomeksowi tomeksowi Dec 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @shushanhf as this change also touches LA

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why change the order ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion, the iiaHasInstrCount and iiaSetInstrCount is not the best at least within the currrent implementation.
I think the LoongArch64's implementation is better than the implementation of the ARM64 and X64.

There is no need to add iiaHasInstrCount and iiaSetInstrCount

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with iiaHasInstrCount is that the disassembler relies on it to check whether the branch is jumping to some label or the offset has been hardcoded in the codegen as a part of some prolog. If the iiaHasInstrCount is not used by the emitter then differentiating between those two cases becomes impossible

Moreover the current LA implementation utilizing iiaEncodedInstr has two major flaws. Firstly, it does not allow the iiaFieldHnd to be set (it takes it place in the union). Secondly, it very often activates two structs in the union itself which is Undefined Behavior by the cpp standard (only one member of the union can be active at the time). This works fine though because the compiler has the extension which allows to type pune trivial types using an union. However in this case the union is not being used to type pune thus this usage is in my opinion an overuse of a feature.

Lets consider this example:

    id->idAddr()->iiaSetInstrEncode(code);
    id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);

In those case two idAddrUnion member are activated: the iiaEncodedInstr and iiaLclVal. But they are not in the same anonymous struct therefore they activate different structs and so this is an UB.

In order to introduce the iiaFieldHnd field back I introduced yet another UB, this time by observing that iiaLclVal is not set in the context where the iiaFieldHnd would be useful. Because iiaFieldHnd occupied the same place in memory as iiaEncodedInstr I switched iiaLclVal and iiaEncodecInstr in theirs structs in order to circumvent this issue.

Because initially I didn't know that there are multiple active members at the same time I've tried to remove unused iiaJmpOffset from the Risc-V implementation but it ended in a crash. I've spend a LOT of time in order to find what was causing a problem. In my opinion the Risc-V implementation should move from the iiaEncodedInstr thus making it more similar with x86/arm64 implementations and getting rid off bugs that are very time consuming to find like this one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with iiaHasInstrCount is that the disassembler relies on it to check whether the branch is jumping to some label or the offset has been hardcoded in the codegen as a part of some prolog. If the iiaHasInstrCount is not used by the emitter then differentiating between those two cases becomes impossible

The iiaHasInstrCount and iiaSetInstrCount should be only used for ARM64/32 and x86/64.
For LA64, this is not needed. And the emit of LA64 is more efficiency than ARM64/32 and x86/64.

Moreover the current LA implementation utilizing iiaEncodedInstr has two major flaws. Firstly, it does not allow the iiaFieldHnd to be set (it takes it place in the union). Secondly, it very often activates two structs in the union itself which is Undefined Behavior by the cpp standard (only one member of the union can be active at the time). This works fine though because the compiler has the extension which allows to type pune trivial types using an union. However in this case the union is not being used to type pune thus this usage is in my opinion an overuse of a feature.

Lets consider this example:

    id->idAddr()->iiaSetInstrEncode(code);
    id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);

In those case two idAddrUnion member are activated: the iiaEncodedInstr and iiaLclVal. But they are not in the same anonymous struct therefore they activate different structs and so this is an UB.

In order to introduce the iiaFieldHnd field back I introduced yet another UB, this time by observing that iiaLclVal is not set in the context where the iiaFieldHnd would be useful. Because iiaFieldHnd occupied the same place in memory as iiaEncodedInstr I switched iiaLclVal and iiaEncodecInstr in theirs structs in order to circumvent this issue.

I will check this later.

Because initially I didn't know that there are multiple active members at the same time I've tried to remove unused iiaJmpOffset from the Risc-V implementation but it ended in a crash. I've spend a LOT of time in order to find what was causing a problem. In my opinion the Risc-V implementation should move from the iiaEncodedInstr thus making it more similar with x86/arm64 implementations and getting rid off bugs that are very time consuming to find like this one.

I don't agree to be more similar with x86/arm64.
In fact, I am now busying with the LoongArch64's Intrinsic which is reviewing and the Native-AOT which debuging, so I don't have enough time to refactor the whole emiter.
But in my plan, after I finish the LoongArch64's Intrinsic which is reviewing and the Native-AOT in 2024, I will refactor the whole emiter, of course implemented within some steps to optimize it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are sure to make RISC-V more similar with x86/arm64 and don't wait the discusses within 2024Q3/Q4, please don't change the LA64's code and don't share with the LA64's code.

Sorry I didn't intend to break your code. The changes have been reverted for the LA architecture

You should not use the iiaHasInstrCount and iiaSetInstrCount which should be only used for ARM64/32 and x86/64 right now, and in fact these can also be optimized later

Could you please provide me with an information how to store an information about the jump origin? I thought the best idea would be to use the iiaHasInstrCount in order to memorize a non-label jump offset but I am open for any suggestions how to improve the current solution

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, @Bajtazar If you can give more info about your problem, maybe I can give you some advices.

some label or the offset has been hardcoded in the codegen as a part of some prolog.

which file and where the loacation ? What the disasmable format you want? by what tools you want this format?

Hi @shushanhf,
For example here the non-labeled branch is being emitted. I would like to capture an information about this in order to print in emitDispIns, for example bne t0, t1, pc+8 (+2 instructions) in the JitDisasm. Moreover, currently if the jump is not hardcoded the jump label is being printed. In the current PR I've done this via setting the iiaSetInstrCount and checking in the disassembly stage to determine which one of them is currently disassembled

Copy link
Contributor

@shushanhf shushanhf Dec 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, @Bajtazar If you can give more info about your problem, maybe I can give you some advices.

some label or the offset has been hardcoded in the codegen as a part of some prolog.

which file and where the loacation ? What the disasmable format you want? by what tools you want this format?

And why you need this format printing ? by which testsing tools requires ?

If you can give me these info, I think I can give some suggestions to solve it tomorrow.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, @Bajtazar If you can give more info about your problem, maybe I can give you some advices.

some label or the offset has been hardcoded in the codegen as a part of some prolog.

which file and where the loacation ? What the disasmable format you want? by what tools you want this format?

Hi @shushanhf, For example here the non-labeled branch is being emitted. I would like to capture an information about this in order to print in emitDispIns, for example bne t0, t1, pc+8 (+2 instructions) in the JitDisasm. Moreover, currently if the jump is not hardcoded the jump label is being printed. In the current PR I've done this via setting the iiaSetInstrCount and checking in the disassembly stage to determine which one of them is currently disassembled

oh, I know, this is very easy for LoongArch64 and RISC-V64, in fact the implementation of the LoongArch64 and RISC-V64 is more efficient than the ARM64/32 and X64/32.
But I have to push the suggestions tomorrow as off duty, is it OK tomorrow?

for example bne t0, t1, pc+8 (+2 instructions) in the JitDisasm.

BTW, why you need this format ? Is it for some testing tools required ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Bajtazar
Maybe you can reference the #96229 , I think there is no need to use iiaHasInstrCount and iiaSetInstrCount for RISCV64.

@clamp03 clamp03 added the arch-riscv Related to the RISC-V architecture label Dec 19, 2023
Copy link
Member

@clamp03 clamp03 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please run coreclr and corefx tests. Thank you!

@clamp03 clamp03 requested a review from jakobbotsch December 20, 2023 01:43
@Bajtazar
Copy link
Contributor Author

Sorry for the late response. I've run the tests and there is no regression there. @jakobbotsch could you please review this PR? The concerns raised in the thread can be addressed in other PRs, this one is only a temporal workaround

@jakobbotsch jakobbotsch merged commit 4d34799 into dotnet:main Jan 10, 2024
tmds pushed a commit to tmds/runtime that referenced this pull request Jan 23, 2024
* Bugfix

* Fixed comparation sign

* Revert "Fixed comparation sign"

This reverts commit c238b82.

* Fixed comparation sign

* Reverted changes in emitOutputInstrJumpDistanceHelper

* Fixed misspell

* Fixes after review

* Reverted changes from la

* Fixed format bug

* Fixed comment

---------

Co-authored-by: Grzegorz Czarnecki <[email protected]>
@github-actions github-actions bot locked and limited conversation to collaborators Feb 10, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-riscv Related to the RISC-V architecture area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants