<p>
Dear developers,
</p>
<p>
<br>
</p>
<p>
As the following code snippet copied from lib/MC/MCParser/AsmParser.cpp shows, when parsing a label, AsmParser::parseStatement calls the onLabelParsed method of a target parser after emitting the label:
</p>
<p>
<br>
</p>
<p>
// Emit the label.<br>
if (!getTargetParser().isParsingInlineAsm())<br>
Out.EmitLabel(Sym, IDLoc);<br>
<br>
// If we are generating dwarf for assembly source files then gather the<br>
// info to make a dwarf label entry for this label if needed.<br>
if (getContext().getGenDwarfForAssembly())<br>
MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),<br>
IDLoc);<br>
<br>
getTargetParser().onLabelParsed(Sym);
</p>
<p>
<br>
</p>
<p>
For ARM, calling onLabelParsed after emitting the label seems to be a bug.
</p>
<p>
<br>
</p>
<p>
If I understand it correctly, ARMAsmParser::onLabelParsed (defined in lib/Target/ARM/AsmParser/ARMAsmParser.cpp) performs two tasks:
</p>
<p>
1) Complete the current implicit IT block (if one is open for new conditional instructions) BEFORE the label, so that the IT block cannot be entered from the middle of it.
</p>
<p>
2) Emit a .thumb_func directive, if the label is the first label following a previously parsed .thumb_func directive without an optional symbol.
</p>
<p>
Considering the tasks above, calling onLabelParsed after the label is emitted leads to two types of errors in the generated code:
</p>
<p>
1) Instructions of an IT block BEFORE the label may be incorrectly emitted AFTER the label.
</p>
<p>
2) .thumb_func directives, which should be emitted BEFORE the corresponding function symbols, are emitted AFTER the function symbols.
</p>
<p>
<br>
</p>
<p>
I tested llvm-mc with the following assembly code:
</p>
<p>
<br>
</p>
<p>
.text<br>
.syntax unified<br>
.p2align 1<br>
.code 16<br>
.globl f1<br>
.globl f2<br>
.thumb_func<br>
f1:<br>
CMP r0, #10<br>
<br>
.thumb_func<br>
<br>
MOVPL r0, #0<br>
<br>
f2:<br>
MOVS r1, #0<br>
.Ltmp:<br>
CMP r0, #0<br>
ITTT PL<br>
ADDPL r1, r1, r0<br>
SUBPL r0, r0, #1<br>
BPL .Ltmp<br>
MOV r0, r1<br>
BX lr<br>
<br>
.end
</p>
<p>
<br>
</p>
<p>
The generated assembly code was as follows:
</p>
<p>
<br>
</p>
<p>
.text<br>
.p2align 1<br>
.code 16<br>
.globl f1<br>
.globl f2<br>
f1:<br>
.thumb_func<br>
cmp r0, #10<br>
<br>
<br>
<br>
f2:<br>
it pl<br>
movpl r0, #0<br>
.thumb_func<br>
movs r1, #0<br>
.Ltmp:<br>
cmp r0, #0<br>
ittt pl<br>
addpl r1, r1, r0<br>
subpl r0, r0, #1<br>
bpl .Ltmp<br>
mov r0, r1<br>
bx lr
</p>
<p>
<br>
</p>
<p>
By comparing the generated assembly code with the original assembly code, it can be seen that both types of errors are present in the generated code.
</p>
<p>
<br>
I tested llvm-mc with the following command line:
</p>
<p>
<br>
</p>
<p>
llvm-mc -arch=thumb -filetype=asm -mattr=+soft-float,-neon,-crypto,+strict-align -mcpu=cortex-m3 -n -triple=armv7m-none-none-eabi -o=it-block-roundtrip.s it-block.S -arm-implicit-it=always
</p>
<p>
<br>
</p>
<p>
where it-block.S is the original assembly file and it-block-roundtrip.s is the generated assembly file.
</p>
<p>
<br>
</p>
<p>
<br>
</p>
<p>
Ming Zhang
</p>