I encounter serval problems about using Global Value (GV) in inline asm. ( both today and before)
I think it is may be a right time to discuss/fix it.
Simply speaking:
We encounter a mangle problem in inlineasm when it directly use Global Value's name.
D113096 once fix the mangle problem. But it cause some other problems.
D115225 and D116090 reverted the D113096 to fix the new fails.
But it didn't fix the mangle problem in inline asm.
So I create 2 patches to fix it.
The first is D120886 (only do revert).
The other is current patch [2/3].
The Next one [3/3] at D121785.
Mangler problem with GV used in inline asm
Currently (and before too) we directly use the GV’s name in inline asm for some cases (I don’t know the early reason, but that doesn’t make sense to me)
For example (Mangler problem)
$cat t.c int GArr[]={0,1,3,}; int foo(int x) { __asm {mov eax, 0}; __asm {mov DWORD PTR GArr[ecx+eax*2+2], 4}; return GArr[x]; }
Let’s compile it with clang -fasm-blocks -target i686-windows-msvc t.c -S
15 _foo: # @foo 16 # %bb.0: # %entry … 29 movl $4, GArr+2(ecx,%eax,2) # inline asm ... 34 movl _GArr(,%eax,4), %eax # read GArr[x] to eax .. 37 retl … 42 _GArr: 43 .long 0 # 0x0 44 .long 1 # 0x1 45 .long 3 # 0x3
Bug: The Mangler didn’t work on the GArr in inline asm, so it can’t rename to _GArr
(Reason: due to we didn’t connected the GArr with its real value in parse process, it just a string name)
History fix (build fail)
I find Shengchen and Pheobe has fix the relation problem before.
They once try to fix it by connecting the GArr with its real value in parse process, but quickly revert it. Because meet 2 fails:
1st Fail: We can't an’t build upper code.
clang -fasm-blocks t.c -S
test.c:5:3: error: BaseReg/IndexReg already set! __asm {mov DWORD PTR GArr[ecx+eax*2+2], 4}; ^ <inline asm>:2:48: note: instantiated into assembly here mov DWORD PTR [rip + offset GArr][ecx + eax * 2 + 2], 4 ^ 1 error generated.
2n Fail: We can’t build upper code in PIC mode even we remove the base reg (this is not a new fail).
int GArr[]={0,1,3,}; int foo(int x) { __asm {mov eax, 0}; __asm {mov DWORD PTR GArr[eax*2+2], 4}; // __asm {mov DWORD PTR GArr[ecx+eax*2+2], 4}; return GArr[x]; }
$clang -fasm-blocks t.c -fpic -S
test.c:5:3: error: base register is 64-bit, but index register is not __asm {mov DWORD PTR GArr[eax*2+2], 4}; ^ <inline asm>:2:16: note: instantiated into assembly here mov DWORD PTR [rax][eax * 2 + 2], 4 ^ 1 error generated.
Status of current LLVM: (has relocation problem in fpic/ GCC too)
$clang -fasm-blocks t-pic.c -fpic -S
… 20 movq GArr@GOTPCREL(%rip), %rax 23 movl $4, **GArr**+2(,%eax,2) # inline asm (not right code, should accessed from GOT) 26 movslq -4(%rbp), %rcx 27 movq GArr@GOTPCREL(%rip), %rax 28 movl (%rax,%rcx,4), %eax # read GArr[x] to eax 31 retq …
Though current llvm successful generate out the code for inline asm, but it is not right code.
Because in PIC mode, the GArr should be accessed from GOT. This will cause segment fault.
How to fix
For GV in inline asm, I prefer to keep the connection between the GV and its real value, (not just keep a GV name in inline asm).
So the GV can be seen in all the optimization pass.
So 1st step, I will revert the patch D115225 and D116090 at D120886
And then 2nd step, I will fix the upper bug Fail 1 (current patch).
Should these change to ${{{[0-9]}}:P} too?