riscv-collab / riscv-gnu-toolchain

GNU toolchain for RISC-V, including GCC
Other
3.53k stars 1.16k forks source link

riscv64-unknown-elf-ld : link error of "R_RISCV_RAL" for "bltu" instruction #626

Closed gxflying closed 4 years ago

gxflying commented 4 years ago

hi, i find it's weird when I compile only one instruction : bltu, I encounter the error : relocation truncated to fit : R_RISCV_JAL against `UND' and from the .o file, I find it actually generated 2 instructions for the bltu:

  1. bgeu
  2. j : this is where the R_RISCV_JAL needed, but not defined

my program is simple: .S : .global _start _start: addi x1, x0 , 0 addi x2, x0, 0 bltu x2, x1, 4 addi x3, x0, 4 lds: OUTPUT_ARCH("riscv") ENTRY(_start) SECTIONS { . = 0X800000000 .text : { *(.text) } _end = . ;

}

command line: see the attachment dddd

aswaterman commented 4 years ago

"bltu x2, x1, 4" means "branch to absolute address 4", which is something you probably don't want to do. You should try branching to a label, rather than branching to an absolute address.

On Tue, Apr 28, 2020 at 4:11 AM Felix notifications@github.com wrote:

hi, i find it's weird when I compile only one instruction : bltu, I encounter the error : relocation truncated to fit : R_RISCV_JAL against `UND' and from the .o file, I find it actually generated 2 instructions for the bltu:

  1. bgeu
  2. j : this is where the R_RISCV_JAL needed, but not defined

my program is simple: .S : .global _start _start: addi x1, x0 , 0 addi x2, x0, 0 bltu x2, x1, 4 addi x3, x0, 4 lds: OUTPUT_ARCH("riscv") ENTRY(_start) SECTIONS { . = 0X800000000 .text : { *(.text) } _end = . ;

}

command line: see the attachment [image: dddd] https://user-images.githubusercontent.com/16956976/80480836-f0afde00-8983-11ea-9a3b-a9c60f32ed9b.png

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/riscv/riscv-gnu-toolchain/issues/626, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAH3XQX5N5455MXHQVNWTN3RO22VPANCNFSM4MSXORAQ .

gxflying commented 4 years ago

@aswaterman thank you for your reply.and i want to go further, sine more questions below:

  1. if I really want to jump from a address above 0x80000000 to the very start of the address , e.g the 0x04, what should I do by using conditional branch instructions?
  2. from the .o file we can see that the bltu acctually was translated into a "bgeu" and a "J" why it behavors like this?
  3. how does the complie option "mcmodel" effect the jump or branch instructions when the offset value is in conserned, for example jump over 2G?
aswaterman commented 4 years ago

1) To jump to an absolute address, you can load it into a register then jr to it--e.g., li t0, 4; jr t0.

2) The assembler emits a conservative sequence if it thinks the branch will go far away.

3) mcmodel primarily affects the C compiler, not the assembler.

On Tue, Apr 28, 2020 at 8:02 AM Felix notifications@github.com wrote:

@aswaterman https://github.com/aswaterman thank you for your reply.and i want to go further, sine more questions below:

  1. if I really want to jump from a address above 0x80000000 to the very start of the address , e.g the 0x04, what should I do by using conditional branch instructions?
  2. from the .o file we can see that the bltu acctually was translated into a "bgeu" and a "J" why it behavors like this? 3.how does the complie option "mcmodel" effect the jump or branch instructions when the offset value is in conserned, for example jump over 2G?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/riscv/riscv-gnu-toolchain/issues/626#issuecomment-620662575, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAH3XQX2PVC7NEGZQEAPVSLRO3VXJANCNFSM4MSXORAQ .

gxflying commented 4 years ago

@aswaterman thanks, about the second question , why does it fail when it enits a far away jump, and it already generats a "J" instruction , besides, the absolute address is also here in the origin instruction. i think it may emits and generates instructions like this: bgeu, x,x,x li x6, 0x04 jr x6 and why not? is the reason that it does not kown which register is avilable to use? or something else?

then in what conditiion the "bgeu & J" series works?

Nelson1225 commented 4 years ago

I think the truncated is caused by two cases,

  1. Like @aswaterman said, the immediate of branch should be a Label in assembler. This may be confusing since RISC-V ISA spec said that the immediate is an offset, and you can also use the immediate as an offset in assembler for many targets. However, the immediate is really an offset when it is relocated and executed. But it is better to be a label when we write the assembly.

  2. The linker script put the text far away from the start of the address. In assembler, we can not know the detailed about the linker script. And it is hard to find an extra register to do what you mentioned (convert bltu to the pattern with jr) in the assemble-time, since we don't preserve an register for temporarily usage in RISC-V ABI. So in the assemble-time, we can only know that you may want to jump to an absolute address by branch, and the range may be not enough. We try our best to convert the branch to a long branch (branch + j), but it may still not far enough.

Maybe you can write your code by C and use compiler with -mcmodel setting, and you probably can resolve the problem. But I remember that there is a long branch issue for compiler, not sure if it is resolved and related to your case.

Thanks

gxflying commented 4 years ago

@Nelson1225 thanks for your answer, I think the same way as you do. and it really is confused for the branch immediate treated as a absolute address while the spec says it's a offset. about the behavior of the assembler, source code may help to understand the machanism. I think it's time to close this issue and thank you again @aswaterman @Nelson1225

Nelson1225 commented 4 years ago

Hi @gxflying,

This document may be helpful, https://github.com/riscv/riscv-asm-manual/blob/master/riscv-asm.md. You can see the details in "Labels".

But I can not find where to describe the above behavior, that is, "bltu x2, x1, 4" means "branch to absolute address 4". Maybe we should add the related description to the document or spec :)

Thanks

gxflying commented 4 years ago

@Nelson1225 Hi, I want to see how the compiler emits the "bltu x2, x1, 4" into two instructions "bgeu & j", and I have got the source code of the gcc with riscv sopported. but it is so hurge that i don't know where to start, could you help me? where the "instruction emits" actions happens? thanks

aswaterman commented 4 years ago

@gxflying https://github.com/bminor/binutils-gdb/blob/master/gas/config/tc-riscv.c#L3112

gxflying commented 4 years ago

@aswaterman thank you very much. I have just found emit_insn() called in the gcc source code in riscv.c.
https://github.com/riscv/riscv-gcc/blob/riscv-gcc-9.2.0/gcc/config/riscv/riscv.c

what i saw is just gcc compiler. and the "emit" happens in gcc assembler you linked above. am I right ?

jim-wilson commented 4 years ago

Yes, the assembler expands the out-of-range branch into two instructions.