[llvm-dev] Bad ARM instruction "sub.w sp, r7, #8" allowed by Clang

Gaël Jobin via llvm-dev llvm-dev at lists.llvm.org
Wed Nov 9 01:53:42 PST 2016


Hi all,

I have a project with Android Studio using a Clang 3.9 for compilation
(built from the source). For those who are not familiar with the NDK
build system, when building JNI library through the ndk-build command,
clang is used to generate assembly file (.s) and then "as" is called to
generate object file (.o).

With ndk r10e, all was working fine. Since ndk r13b, I got an error
during the compilation.

When building my project with -O0, it is still working. But building it
with -O1 with ndk r13b, I got many messages like:

Error: r13 not allowed here -- 'sub.w sp,r7,#8'

I found out that under ndk r10e, the compilation was made in arm mode.
Under ndk r13b, the compilation is made in thumb mode. So passing
-mthumb with ndk r10e produce the same error.


The generated instruction "sub.w sp,r7,#8" is illegal (A8.8.223 T2).
When Rd equal to SP, it must use the "SUB (SP minus register)" synthax
(A8.8.225 T2) which explicitly allows only SP as Rn (source).

Using -mllvm -print-after-all, the bad t2SUBri instruction seems to
appear right after the RegisterCoalescer pass.

Looking at gas source code, the check is made correctly in
"gas/config/tc-arm.c" inside functions do_t_add_sub_w()/do_t_add_sub().
This is the reason of the error above.

Now, in the Clang side, inside "lib/Target/ARM/ARMInstrThumb2.td", we
have the following:

defm t2ADD  : T2I_bin_ii12rs<0b000, "add", add, 1>;
defm t2SUB  : T2I_bin_ii12rs<0b101, "sub", sub>;

T2I_bin_ii12rs is a multiclass which define t2SUBri, t2SUBri12, t2SUBrr
and t2SUBrs. The problem is that the register class used for the
destination register is always set to GPRnopc which include SP. As I
don't now enough about TableGen to put a constraint like "if
destination register is SP, only SP is allowed as a source register", I
simply replaced destination register GPRnopc to tGPR for ri,ri12,rr and
rs. Then I updated all alias (t2InstAlias) that use
t2ADD{ri,ri12,rr,rs} and t2SUB{ri,ri12,rr,rs} by replacing GPRnopc by
tGPR.

This fix has allowed me to compile my project again without error !!!

Given that it is the first time I mess with the ARM backend, what do
you think of this fix? Did I miss something? As the fix is not complete
(it does not support the "SUB (SP minus register)"), any idea how to
implement this special instruction ?

Thank you

Regards,
Gael




More information about the llvm-dev mailing list