@@ -8,6 +8,7 @@ use crate::isa::riscv64::lower::isle::generated_code::{
88use cranelift_control:: ControlPlane ;
99
1010pub struct EmitInfo {
11+ #[ expect( dead_code, reason = "may want to be used in the future" ) ]
1112 shared_flag : settings:: Flags ,
1213 isa_flags : super :: super :: riscv_settings:: Flags ,
1314}
@@ -170,7 +171,9 @@ impl Inst {
170171 | Inst :: ReturnCallInd { .. }
171172 | Inst :: Jal { .. }
172173 | Inst :: CondBr { .. }
173- | Inst :: LoadExtName { .. }
174+ | Inst :: LoadExtNameGot { .. }
175+ | Inst :: LoadExtNameNear { .. }
176+ | Inst :: LoadExtNameFar { .. }
174177 | Inst :: ElfTlsGetAddr { .. }
175178 | Inst :: LoadAddr { .. }
176179 | Inst :: Mov { .. }
@@ -1999,76 +2002,108 @@ impl Inst {
19992002 . emit ( sink, emit_info, state) ;
20002003 }
20012004
2002- & Inst :: LoadExtName {
2005+ & Inst :: LoadExtNameGot { rd, ref name } => {
2006+ // Load a PC-relative address into a register.
2007+ // RISC-V does this slightly differently from other arches. We emit a relocation
2008+ // with a label, instead of the symbol itself.
2009+ //
2010+ // See: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#pc-relative-symbol-addresses
2011+ //
2012+ // Emit the following code:
2013+ // label:
2014+ // auipc rd, 0 # R_RISCV_GOT_HI20 (symbol_name)
2015+ // ld rd, rd, 0 # R_RISCV_PCREL_LO12_I (label)
2016+
2017+ // Create the label that is going to be published to the final binary object.
2018+ let auipc_label = sink. get_label ( ) ;
2019+ sink. bind_label ( auipc_label, & mut state. ctrl_plane ) ;
2020+
2021+ // Get the current PC.
2022+ sink. add_reloc ( Reloc :: RiscvGotHi20 , & * * name, 0 ) ;
2023+ Inst :: Auipc {
2024+ rd,
2025+ imm : Imm20 :: from_i32 ( 0 ) ,
2026+ }
2027+ . emit_uncompressed ( sink, emit_info, state, start_off) ;
2028+
2029+ // The `ld` here, points to the `auipc` label instead of directly to the symbol.
2030+ sink. add_reloc ( Reloc :: RiscvPCRelLo12I , & auipc_label, 0 ) ;
2031+ Inst :: Load {
2032+ rd,
2033+ op : LoadOP :: Ld ,
2034+ flags : MemFlags :: trusted ( ) ,
2035+ from : AMode :: RegOffset ( rd. to_reg ( ) , 0 ) ,
2036+ }
2037+ . emit_uncompressed ( sink, emit_info, state, start_off) ;
2038+ }
2039+
2040+ & Inst :: LoadExtNameFar {
20032041 rd,
20042042 ref name,
20052043 offset,
20062044 } => {
2007- if emit_info. shared_flag . is_pic ( ) {
2008- // Load a PC-relative address into a register.
2009- // RISC-V does this slightly differently from other arches. We emit a relocation
2010- // with a label, instead of the symbol itself.
2011- //
2012- // See: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#pc-relative-symbol-addresses
2013- //
2014- // Emit the following code:
2015- // label:
2016- // auipc rd, 0 # R_RISCV_GOT_HI20 (symbol_name)
2017- // ld rd, rd, 0 # R_RISCV_PCREL_LO12_I (label)
2018-
2019- // Create the label that is going to be published to the final binary object.
2020- let auipc_label = sink. get_label ( ) ;
2021- sink. bind_label ( auipc_label, & mut state. ctrl_plane ) ;
2022-
2023- // Get the current PC.
2024- sink. add_reloc ( Reloc :: RiscvGotHi20 , & * * name, 0 ) ;
2025- Inst :: Auipc {
2026- rd,
2027- imm : Imm20 :: from_i32 ( 0 ) ,
2028- }
2029- . emit_uncompressed ( sink, emit_info, state, start_off) ;
2045+ // In the non PIC sequence we relocate the absolute address into
2046+ // a preallocated space, load it into a register and jump over
2047+ // it.
2048+ //
2049+ // Emit the following code:
2050+ // ld rd, label_data
2051+ // j label_end
2052+ // label_data:
2053+ // <8 byte space> # ABS8
2054+ // label_end:
20302055
2031- // The `ld` here, points to the `auipc` label instead of directly to the symbol.
2032- sink. add_reloc ( Reloc :: RiscvPCRelLo12I , & auipc_label, 0 ) ;
2033- Inst :: Load {
2034- rd,
2035- op : LoadOP :: Ld ,
2036- flags : MemFlags :: trusted ( ) ,
2037- from : AMode :: RegOffset ( rd. to_reg ( ) , 0 ) ,
2038- }
2039- . emit_uncompressed ( sink, emit_info, state, start_off) ;
2040- } else {
2041- // In the non PIC sequence we relocate the absolute address into
2042- // a prealocatted space, load it into a register and jump over it.
2043- //
2044- // Emit the following code:
2045- // ld rd, label_data
2046- // j label_end
2047- // label_data:
2048- // <8 byte space> # ABS8
2049- // label_end:
2050-
2051- let label_data = sink. get_label ( ) ;
2052- let label_end = sink. get_label ( ) ;
2053-
2054- // Load the value from a label
2055- Inst :: Load {
2056- rd,
2057- op : LoadOP :: Ld ,
2058- flags : MemFlags :: trusted ( ) ,
2059- from : AMode :: Label ( label_data) ,
2060- }
2061- . emit ( sink, emit_info, state) ;
2056+ let label_data = sink. get_label ( ) ;
2057+ let label_end = sink. get_label ( ) ;
20622058
2063- // Jump over the data
2064- Inst :: gen_jump ( label_end) . emit ( sink, emit_info, state) ;
2059+ // Load the value from a label
2060+ Inst :: Load {
2061+ rd,
2062+ op : LoadOP :: Ld ,
2063+ flags : MemFlags :: trusted ( ) ,
2064+ from : AMode :: Label ( label_data) ,
2065+ }
2066+ . emit ( sink, emit_info, state) ;
20652067
2066- sink. bind_label ( label_data, & mut state. ctrl_plane ) ;
2067- sink. add_reloc ( Reloc :: Abs8 , name. as_ref ( ) , offset) ;
2068- sink. put8 ( 0 ) ;
2068+ // Jump over the data
2069+ Inst :: gen_jump ( label_end) . emit ( sink, emit_info, state) ;
20692070
2070- sink. bind_label ( label_end, & mut state. ctrl_plane ) ;
2071+ sink. bind_label ( label_data, & mut state. ctrl_plane ) ;
2072+ sink. add_reloc ( Reloc :: Abs8 , name. as_ref ( ) , offset) ;
2073+ sink. put8 ( 0 ) ;
2074+
2075+ sink. bind_label ( label_end, & mut state. ctrl_plane ) ;
2076+ }
2077+
2078+ & Inst :: LoadExtNameNear {
2079+ rd,
2080+ ref name,
2081+ offset,
2082+ } => {
2083+ // Emit the following code:
2084+ // label:
2085+ // auipc rd, 0 # R_RISCV_PCREL_HI20 (symbol_name)
2086+ // ld rd, rd, 0 # R_RISCV_PCREL_LO12_I (label)
2087+
2088+ let auipc_label = sink. get_label ( ) ;
2089+ sink. bind_label ( auipc_label, & mut state. ctrl_plane ) ;
2090+
2091+ // Get the current PC.
2092+ sink. add_reloc ( Reloc :: RiscvPCRelHi20 , & * * name, offset) ;
2093+ Inst :: Auipc {
2094+ rd,
2095+ imm : Imm20 :: from_i32 ( 0 ) ,
2096+ }
2097+ . emit_uncompressed ( sink, emit_info, state, start_off) ;
2098+
2099+ sink. add_reloc ( Reloc :: RiscvPCRelLo12I , & auipc_label, 0 ) ;
2100+ Inst :: AluRRImm12 {
2101+ alu_op : AluOPRRI :: Addi ,
2102+ rd,
2103+ rs : rd. to_reg ( ) ,
2104+ imm12 : Imm12 :: ZERO ,
20712105 }
2106+ . emit_uncompressed ( sink, emit_info, state, start_off) ;
20722107 }
20732108
20742109 & Inst :: ElfTlsGetAddr { rd, ref name } => {
0 commit comments