<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>