In Linux PIC model, Global Address (GA) of Global Variable (GV) will be got from loading GOT slot.
Different instructions has different understanding about using Global Address.
For example in X86:
- We assign a value to GV, we can use "MOV GV, ...", it corresping to "MOV (Global Address) ...".
- We got related address of GV, we can use "LEA GV, ...", it corresping to "LEA (Global Address) ...".
- But if we call the label (GV can be a label), we can use "CALL GV", it didn't equal with "CALL (Global Address)".
So, it is obvious that Global Address of Global Variable should be specially handled case by case.
This is done in normal IR/MIR which has "single" purpose use of the Global Address.
But things changed in inline asm which represented by only one IR/MIR but may contains
a lot of instructions with mult-purpose on same or different Global Address.
What is more, llvm didn't distinguish the instructions in inline asm IR/MIR.
TODO: The other targets may also has this problem, we need to fix them too. It is an arch defect for llvm inline asm.
Take a concrete example: test.c: (clang t.c -fasm-blocks -S -fpic -emit-llvm test.c )
extern void sincos(); int GV=3; int Arr[10] = {1,}; void foo() { asm { lea r8, Arr mov rax, GV lea r9, sincos call sincos ret } }
it will generate following wrong code:
movq sincos@GOTPCREL(%rip), %rsi movq GV@GOTPCREL(%rip), %rdx movq Arr@GOTPCREL(%rip), %rcx #APP leaq (%rcx), %r8 movq (%rdx), %rax // Not like "MOV GV", CALL don't get the context of the Function sincos leaq (%rsi), %r9 // Not like "LEA sincos", LEA can get the address without Dereference callq *(%rsi) // It should directly call the sincos --> callq %rsi --> in normal case (non-large code model) it should be "**call sincos@PLT**" retq #NO_APP
clang-format: please reformat the code