ZhiyaoMa98 added a comment.

> Can you describe a little more what you're trying to do here?

Sure. My eventual goal is to enable fine-granular live-update on ARM based 
microcontrollers, which requires the system to do some relocation at runtime. 
Below I will describe the challenge with a simple C example.

Consider the following C snippet:

  extern void global_func(void); // A global function whose symbol is exported 
by the system at runtime.
  static void local_func(void) { ... }
  
  static void main_entry(void) {
      local_func();
      global_func();
  }

I want to load and run the compiled object file at runtime, which requires two 
steps.

1. Burn the object file into Flash storage.
2. Perform a runtime symbol resolution and relocation so that `global_func` is 
set to the runtime address.

The reason why I must store code in Flash storage is that the microcontroller I 
am using, as well as many other ARM based microcontrollers, has Flash storage 
5x greater than RAM, and code typically directly runs from Flash.

`local_func` requires the compiler to use position independent code, which has 
already been handled by `-fropi`. `global_func` however, is the case I am 
trying to solve here.

Existing compiler options always store the address of `global_func` in Flash.

The default case:

  main_entry:
      bl  local_func
      b.w global_func // Relative address is hardcoded in the instruction, in 
Flash.

If compile with `-mlong-calls`:

  main_entry:
      bl  local_func
      ldr r0, [pc, #4] // Load address from constant pool, still in Flash.
      bx  r0
  .Lconst_pool:
      .word global_func

In the hypothetical case if the compiler chose to use `movw` `movt` pair:

  main_entry:
      bl   local_func
      movw r0, :lower16:global_func // Absolute address is hardcoded in the 
instruction, still in Flash.
      movt r0, :upper16:global_func
      bx.  r0

I was expecting to use the "side effect" of `-mexecute-only` that promotes 
constant pools to global variables to achieve my goal of having the function 
address to live in RAM.

  main_entry:
      bl   local_func
      movw r0, :lower16:.const_pool(sbrel) // Absolute address is held in RAM 
now.
      movt r0, :upper16:.const_pool(sbrel) // Also using RWPI so that the jump 
table can be placed anywhere in RAM pointed by r9.
      ldr  r0, [r9, r0]
      bx   r0

As you have already pointed out, in the normal case when we do not need to put 
the address in RAM, the extra indirection is unnecessary and slows down the 
code.

But if I have a use case like above where I need to store the address in RAM, 
could you enlighten me about the best approach to achieve my goal?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136203/new/

https://reviews.llvm.org/D136203

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to